我目前正在处理有一些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秒)。
请解释一下该查询的含义,以及如何简化和改进它。
答案 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作为获取此相同查询结果的另一个创意选项