如何提高这个mysql查询处理的速度

时间:2014-10-07 16:15:10

标签: php mysql sql

我目前正在处理有一些mysql查询的项目。项目中的所有mysql查询都是由另一个开发人员完成的。无论如何,我对他在下面所做的查询有点困惑:

SELECT MIN(s_date) AS s_date, 
       client_id
FROM tb1 
WHERE flag = 1 
    AND client_id NOT IN (
        SELECT DISTINCT client_id 
        FROM tb1 
        WHERE flag = 0
    ) 
GROUP BY client_id;

查询的第一部分是检查flag = 1,第二部分是否检查NOT IN(flag = 0)。我认为它有点多余,因为flag = 1,它不能为0.我不理解该查询的逻辑。而且我认为NOT IN有点慢(我的数据库需要2秒)。

请解释一下该查询的含义,以及如何简化和改进它。

3 个答案:

答案 0 :(得分:1)

您似乎总结了标志永远不会0的客户端。查询更简单地写为:

SELECT MIN(s_date) s_date, 
       client_id F
FROM tb1 
WHERE flag in (0, 1)
GROUP BY client_id
HAVING SUM(flag = 0) = 0;

这也可以提高性能。

答案 1 :(得分:0)

在大多数数据库中,使用“not in”简单,直观,但速度慢。有时您可以这样解决:

where myfield in 
(select myfield 
where I want it
minus
select myfield 
where I want to exclude it)

有些数据库使用的是“except”而不是“minus”。我不认为这适用于mySql,所以你必须做这样的事情:

select somefields
from sometables
left join (
select idfield, someOtherField
from blah 
where I want to exclude it
) temp on sometable on sometable.idfield = temp.idfield
and temp.someOtherField is null

答案 2 :(得分:0)

以下是您的想法:

在子选择中,您将找到至少有一条记录,其中flag = 0的client_id列表。

然后,您可以从主查询中排除该ID列表。

所以,如果你有这样的样本数据:

client_id   flag    s_date
---------   ----    ------
1           1       2014-01-01
2           0       2014-02-01
2           1       2014-03-01
3           0       2014-04-01
4           1       2014-05-01
4           1       2014-06-01

您的查询只会返回:

s_date       client_id
------       ---------
2014-01-01   1
2014-05-01   4

实际上在您的查询中,flag的冗余使用实际上是在主查询中。因为你已经在子选择中删除了任何flag = 0值的所有client_id,所以根本不需要它。

就优化查询而言。这是其中一种情况,即子选择可能比连接快,也可能不是。它实际上取决于数据行数,满足子选择条件的行数等等(当然假设所有正确的索引都已到位)。

您可以尝试这样的自我加入,看看哪种效果更适合您:

SELECT
    MIN(a.s_date) AS s_date,
    a.client_id AS client_id
FROM tbl AS a LEFT JOIN (
    SELECT DISTINCT client_id 
    FROM tb1 
    WHERE flag = 0
) AS b
ON a.client_id = b.client_id
WHERE b.client IS NULL
GROUP BY a.client_id

另请尝试使用@GordonLinoff作为获取此相同查询结果的另一个创意选项

相关问题