在子查询中选择列为空的位置

时间:2012-03-07 05:26:24

标签: mysql sql

我有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。

2 个答案:

答案 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