304

如果我有一张桌子

CREATE TABLE users (
  id int(10) unsigned NOT NULL auto_increment,
  name varchar(255) NOT NULL,
  profession varchar(255) NOT NULL,
  employer varchar(255) NOT NULL,
  PRIMARY KEY  (id)
)

我想获得profession字段的所有唯一值,什么会更快(或推荐):

SELECT DISTINCT u.profession FROM users u

或者

SELECT u.profession FROM users u GROUP BY u.profession

?

4

16 回答 16

284

它们本质上是等价的(实际上这就是一些数据库在后台实现DISTINCT的方式)。

如果其中一个更快,它将是DISTINCT. 这是因为,尽管两者是相同的,但查询优化器必须抓住这样一个事实,即您GROUP BY没有利用任何组成员,而只是利用他们的键。DISTINCT明确这一点,因此您可以使用稍微笨拙的优化器。

如有疑问,请测试!

于 2009-02-24T12:09:22.143 回答
109

如果您对 有索引profession,则这两个是同义词。

如果你不这样做,那么使用DISTINCT.

GROUP BYMySQL排序结果中。你甚至可以这样做:

SELECT u.profession FROM users u GROUP BY u.profession DESC

并按顺序排列您的职业DESC

DISTINCT创建一个临时表并将其用于存储重复项。GROUP BY做同样的事情,但之后对不同的结果进行排序。

所以

SELECT DISTINCT u.profession FROM users u

如果您没有索引,则速度会更快profession

于 2009-02-27T14:50:08.283 回答
26

对于单列上的 DISTINCT 与单列上的 GROUP BY 的情况,上述所有答案都是正确的。每个数据库引擎都有自己的实现和优化,如果您关心非常小的差异(在大多数情况下),那么您必须针对特定服务器和特定版本进行测试!由于实施可能会改变......

但是,如果您在查询中选择多个列,则 DISTINCT 本质上是不同的!因为在这种情况下,它将比较所有行的所有列,而不仅仅是一列。

所以如果你有类似的东西:

// This will NOT return unique by [id], but unique by (id,name)
SELECT DISTINCT id, name FROM some_query_with_joins

// This will select unique by [id].
SELECT id, name FROM some_query_with_joins GROUP BY id

认为 DISTINCT 关键字通过您指定的第一列来区分行是一个常见的错误,但 DISTINCT 是这种方式的通用关键字。

因此,您必须小心不要将上述答案视为对所有情况都是正确的……您可能会感到困惑并得到错误的结果,而您想要的只是优化!

于 2013-05-16T10:49:53.613 回答
17

如果可以,请选择最简单和最短的 - DISTINCT 似乎更符合您的要求,只是因为它会为您提供您需要的答案,而且仅此而已!

于 2009-02-24T13:37:28.670 回答
8

在 postgres 中的某些情况下,well distinct 可能比 group by 慢(不知道其他数据库)。

测试示例:

postgres=# select count(*) from (select distinct i from g) a;

count 

10001
(1 row)

Time: 1563,109 ms

postgres=# select count(*) from (select i from g group by i) a;

count
10001
(1 row)

Time: 594,481 ms

http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I

所以要小心...... :)

于 2011-11-18T13:56:26.670 回答
7

Group by 比 Distinct 昂贵,因为 Group by 对结果进行排序,而 distinct 避免了它。但是,如果你想让 group by 产生与 distinct 相同的结果给order by null ..

SELECT DISTINCT u.profession FROM users u

等于

SELECT u.profession FROM users u GROUP BY u.profession order by null
于 2013-06-21T01:09:18.553 回答
5

查询似乎并不完全相同。至少对于 MySQL。

比较:

  1. 描述从 northwind.products 中选择不同的产品名称
  2. 按产品名称描述从 northwind.products 组中选择产品名称

第二个查询在 Extra 中另外给出了“使用文件排序”。

于 2009-02-24T12:20:18.247 回答
3

MySQL中," Group By" 使用了一个额外的步骤:filesort. 我意识到DISTINCT比 快GROUP BY,这是一个惊喜。

于 2014-02-11T18:27:20.043 回答
3

经过大量测试,我们得出的结论是 GROUP BY 更快

SELECT sql_no_cache opnamegroep_intern FROM telwerken WHERE opnemergroepIN (7,8,9,10,11,12,13)​​ group by opnamegroep_intern

总共 635 条 0.0944 秒 Weergave van 记录 0 - 29 条(总共 635 条,查询 duurde 0.0484 秒)

SELECT sql_no_cache distinct (opnamegroep_intern) FROM telwerken WHERE opnemergroepIN (7,8,9,10,11,12,13)

635 总 0.2117 秒(几乎 100% 慢) Weergave van 记录 0 - 29 (635 总,查询 duurde 0.3468 秒)

于 2015-06-09T09:12:37.410 回答
2

(更多功能说明)

在某些情况下,您必须使用 GROUP BY,例如,如果您想获取每个雇主的雇员人数:

SELECT u.employer, COUNT(u.id) AS "total employees" FROM users u GROUP BY u.employer

在这种情况下DISTINCT u.employer无法正常工作。也许有办法,但我就是不知道。(如果有人知道如何使用 DISTINCT 进行此类查询,请添加注释!)

于 2012-05-21T17:15:41.027 回答
2

这是一个简单的方法,它将为每个查询打印 2 个不同的经过时间。

DECLARE @t1 DATETIME;
DECLARE @t2 DATETIME;

SET @t1 = GETDATE();
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

SET @t1 = GETDATE();
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

或尝试SET STATISTICS TIME (Transact-SQL)

SET STATISTICS TIME ON;
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET STATISTICS TIME OFF;

它只是显示解析、编译和执行每条语句所需的毫秒数,如下所示:

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 2 ms.
于 2016-06-03T09:56:42.863 回答
1

这不是规则

对于每个查询 .... 分别尝试 distinct 然后分组 ... 比较完成每个查询的时间并使用更快的 ....

在我的项目中,有时我使用 group by 和其他不同的

于 2015-07-16T23:24:28.337 回答
0

如果您不必执行任何组函数(求和、平均值等,以防您想将数字数据添加到表中),请使用 SELECT DISTINCT。我怀疑它更快,但我没有什么可证明的。

无论如何,如果您担心速度,请在列上创建索引。

于 2009-02-24T12:09:28.150 回答
0

SELECT DISTINCT 将始终与 GROUP BY 相同或更快。在某些系统(即 Oracle)上,它可能被优化为与大多数查询的 DISTINCT 相同。在其他(如 SQL Server)上,它可能会快得多。

于 2009-02-27T14:55:01.720 回答
0

如果问题允许,请尝试使用 EXISTS,因为它已优化为在找到结果后立即结束(并且不缓冲任何响应),因此,如果您只是尝试为这样的 WHERE 子句规范化数据

SELECT FROM SOMETHING S WHERE S.ID IN ( SELECT DISTINCT DCR.SOMETHING_ID FROM DIFF_CARDINALITY_RELATIONSHIP DCR ) -- to keep same cardinality

更快的响应是:

SELECT FROM SOMETHING S WHERE EXISTS ( SELECT 1 FROM DIFF_CARDINALITY_RELATIONSHIP DCR WHERE DCR.SOMETHING_ID = S.ID )

这并不总是可能的,但如果可用,您会看到更快的响应。

于 2014-06-09T19:37:04.070 回答
0

在 mySQL 中,我发现 GROUP BY 会将 NULL 视为不同的,而 DISTINCT 不会。
采用完全相同的 DISTINCT 查询,删除 DISTINCT,并将所选字段添加为 GROUP BY,由于其中一个字段为 NULL,我得到了更多行。

所以.. 我倾向于相信 mySQL 中的 DISTINCT 更多。

于 2021-10-09T23:06:04.880 回答