MySQL:WHERE子选择中GROUP BY的奇怪行为

时间:2017-04-07 11:34:11

标签: mysql sql

我希望你能帮助我解决这个话题。

我有一个表,相关字段是VARCHAR id,VARCHAR名称和日期

3DF0001AB    TESTING_1    2017-04-04
3DF0002ZG    TESTING_2    2017-04-03
3DF0003ER    TESTING_1    2017-04-01
3DF0004XY    TESTING_1    2017-03-26
3DF0005UO    TESTING_3    2017-03-25

目标是为每个名称(> 500)检索两个条目,按日期排序。因为我可以使用数据库查询,我尝试了以下方法。为每个名称获取一个id,UNION使用相同的查询获得结果,但不包括第一组中的ID。

第一步是为每个名字输入一个条目。按预期结果,每个名称都有一个id。

SELECT id FROM table GROUP BY name;

第二步;使用WHERE子句中的上述语句来接收不在第一个结果中的结果:

SELECT id FROM table WHERE id NOT IN (SELECT id FROM table GROUP BY name)

但是结果是空的,然后我尝试使用WHERE id IN而不是NOT IN来反转WHERE。预期的结果是,只使用子查询时会显示相同的id,结果是表中的所有ID。所以我假设子查询提供了错误的结果,因为当我手动复制id时,> id IN ("3DF0001AB", ...)它有效。

所以也许有人可以解释行为和/或帮助找到原始问题的解决方案。

1 个答案:

答案 0 :(得分:1)

这是一个非常糟糕的做法:

SELECT id
FROM table
GROUP BY name;

虽然MySQL允许此构造,但返回的id来自 indeterminate 行。在不同的时间运行相同的查询时,甚至可以获得不同的行。

更好的方法是使用聚合函数:

SELECT MAX(id)
FROM table
GROUP BY name;

但你真正的问题却略有不同。使用NOT IN时,如果IN列表中的任何值为NULL,则不会返回任何行。这就是定义NOT IN的方式。

我建议改用NOT EXISTSLEFT JOIN,因为他们的行为更直观:

SELECT t.id
FROM table t LEFT JOIN
     (SELECT MAX(id) as id
      FROM table t2
      GROUP BY name
     ) tt
     ON t.id = tt.id
WHERE tt.id IS NULL;