我有2个表,其中包含与这些名称相关的名称和日期安排。我试图获取一份从未安排过或未在过去2个月内安排过的所有姓名的清单。
SELECT n.name, MAX(s.date)
FROM names n
LEFT JOIN schedule s ON n.id = s.nameid
WHERE s.nameid IS NULL
OR s.nameid NOT IN (SELECT nameid
FROM schedule
WHERE date > NOW() - INTERVAL 2 MONTH)
GROUP BY n.id
当我运行此查询时,MySQL接管CPU并且不响应。
当我将其更改为其中任何一个时,我得到的结果,但只有我要找的结果的一半:
SELECT n.name, MAX(s.date)
FROM names n
LEFT JOIN schedule s ON n.id = s.nameid
WHERE s.nameid IS NULL
GROUP BY n.id
SELECT n.name, MAX(s.date)
FROM names n
LEFT JOIN schedule s ON n.id = s.nameid
WHERE s.nameid NOT IN (SELECT nameid
FROM schedule
WHERE date > NOW() - INTERVAL 2 MONTH)
GROUP BY n.id
我不确定如何让这个查询返回所有结果或者它为什么会占用CPU。
答案 0 :(得分:1)
OR
是一个臭名昭着的糟糕表演者,在我能想到的每个数据库中。 UNION
通常是更好的选择:
SELECT n.name, MAX(s.date)
FROM names n
LEFT JOIN schedule s ON n.id = s.nameid
WHERE s.nameid IS NULL
GROUP BY n.id
UNION
SELECT n.name, MAX(s.date)
FROM names n
LEFT JOIN schedule s ON n.id = s.nameid
WHERE s.nameid NOT IN (SELECT nameid
FROM schedule
WHERE date > NOW() - INTERVAL 2 MONTH)
GROUP BY n.id
UNION
会删除重复项 - 如果不关心重复项,请使用UNION ALL
(它更快,因为它不会删除重复项。)
此外,后一个查询在WHERE子句中具有针对OUTER JOIN'd表的条件 - 此条件在 JOIN之后应用。使用以下方法可能会得到不同的结果:
SELECT n.name, MAX(s.date)
FROM names n
LEFT JOIN schedule s ON s.nameid = n.id
AND s.nameid NOT IN (SELECT nameid
FROM schedule
WHERE date > NOW() - INTERVAL 2 MONTH)
GROUP BY n.id
在上面的示例中,标准将在 OUTER JOIN之前应用。对于INNER JOIN,可以忽略这一点 - 任一点中的标准都是等效的。
答案 1 :(得分:0)
在不知道您的完整架构的情况下,
是否有问题 SELECT n.name, max(s.date)
FROM names n
LEFT JOIN schedule s
ON n.id = s.nameid
WHERE s.nameid IS NULL
OR s.date <= DATE_SUB(CURDATE(), INTERVAL 2 MONTH)
GROUP BY n.id