在 MySQL 查询中,当使用 DISTINCT
选项时,是否在删除重复项后应用 ORDER BY
?如果没有,有什么办法让它这样做吗?我认为这会导致我的代码出现一些问题。
编辑:
以下是有关导致我的问题的原因的更多信息。我知道,乍一看,这个顺序并不重要,因为我正在处理重复的行。然而,情况并非完全如此,因为我正在使用 INNER JOIN
对行进行排序。
假设我有一张论坛主题表,其中包含以下数据:
+----+--------+-------------+
| id | userid | title |
+----+--------+-------------+
| 1 | 1 | Information |
| 2 | 1 | FAQ |
| 3 | 2 | Support |
+----+--------+-------------+
我在另一个表中也有一组这样的帖子:
+----+----------+--------+---------+
| id | threadid | userid | content |
+----+----------+--------+---------+
| 1 | 1 | 1 | Lorem |
| 2 | 1 | 2 | Ipsum |
| 3 | 2 | 2 | Test |
| 4 | 3 | 1 | Foo |
| 5 | 2 | 3 | Bar |
| 6 | 3 | 5 | Bob |
| 7 | 1 | 2 | Joe |
+----+----------+--------+---------+
我正在使用以下 MySQL 查询来获取所有线程,然后根据最新帖子对它们进行排序(假设具有更高 ID 的帖子是最近的:
SELECT t.*
FROM Threads t
INNER JOIN Posts p ON t.id = p.threadid
ORDER BY p.id DESC
这行得通,并生成如下内容:
+----+--------+-------------+
| id | userid | title |
+----+--------+-------------+
| 1 | 1 | Information |
| 3 | 2 | Support |
| 2 | 1 | FAQ |
| 3 | 2 | Support |
| 2 | 1 | FAQ |
| 1 | 1 | Information |
| 1 | 1 | Information |
+----+--------+-------------+
但是,正如你所看到的,信息是正确的,但是有重复的行。我想删除此类重复项,所以我改用了 SELECT DISTINCT
。但是,这产生了以下结果:
+----+--------+-------------+
| id | userid | title |
+----+--------+-------------+
| 3 | 2 | Support |
| 2 | 1 | FAQ |
| 1 | 1 | Information |
+----+--------+-------------+
这显然是错误的,因为“信息”线程应该在最上面。似乎使用 DISTINCT
会导致从上到下删除重复项,因此只剩下最后几行。这会导致排序出现一些问题。
是这样吗,还是我分析不正确?
最佳答案
需要理解的两件事:
一般来说,结果集是 unordered除非您指定一个
ORDER BY
子句;在您指定 non-strict order 的范围内(即ORDER BY
在非唯一列上),在该排序下相等的记录出现在结果集中的顺序是未定义的。我怀疑您可能指定了这样一个非严格的顺序,这是您问题的根源:通过在一组足以唯一标识您关心的每条记录在结果集中的最终位置。
DISTINCT
may useGROUP BY
,这会导致结果按分组列排序;也就是说,SELECT DISTINCT a, b, c FROM t
将生成一个结果集,看起来好像已应用了ORDER BY a, b, c
。同样,指定足够严格的顺序以满足您的需求将覆盖此效果。
根据您的更新,请记住我上面的第 2 点,很明显,对结果进行分组以实现 DISTINCT
的效果使得无法按未分组的列 进行排序>p.id
;相反,你想要:
SELECT t.*
FROM Threads t INNER JOIN Posts p ON t.id = p.threadid
GROUP BY t.id
ORDER BY MAX(p.id) DESC
关于php - ORDER BY 应用在 DISTINCT 之前还是之后?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10905026/