如果我有桌子
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
答案 0 :(得分:234)
它们本质上是相互对应的(实际上这是一些数据库在引擎盖下实现DISTINCT
的方式)。
如果其中一个更快,那将是DISTINCT
。这是因为,虽然两者是相同的,但查询优化器必须注意到GROUP BY
没有利用任何组成员,只有他们的密钥的事实。 DISTINCT
明确表示这一点,因此您可以使用略微笨拙的优化器。
如有疑问,请测试!
答案 1 :(得分:98)
如果您在profession
上有索引,则这两个是同义词。
如果不这样做,请使用DISTINCT
。
GROUP BY
中的 MySQL
对结果进行排序。你甚至可以这样做:
SELECT u.profession FROM users u GROUP BY u.profession DESC
并按DESC
顺序排列您的专业。
DISTINCT
创建一个临时表,并使用它来存储重复项。 GROUP BY
也会这样做,但之后会对不同的结果进行排序。
所以
SELECT DISTINCT u.profession FROM users u
如果您在profession
上没有索引,会更快。
答案 2 :(得分:17)
如果可以的话,选择最简单和最短的方式 - DISTINCT似乎更符合您的要求,因为它只会为您提供所需的答案而且只有这一点!
答案 3 :(得分:15)
上述所有答案都是正确的,对于单列上的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是这种方式的通用关键字。
所以人们必须小心,不要将上面的答案视为对所有情况都是正确的......你可能会感到困惑并得到错误的结果,而你想要的只是优化!
答案 4 :(得分:7)
很明显可能比分组慢。
测试示例:
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
所以要小心......:)
答案 5 :(得分:7)
Group by比Distinct贵,因为Group by对结果进行了排序,同时避免了它。但是,如果你想通过产生相同的结果而得到与 按黄色相同的结果 ..
SELECT DISTINCT u.profession FROM users u
等于
SELECT u.profession FROM users u GROUP BY u.profession order by null
答案 6 :(得分:5)
似乎查询不完全相同。至少对于MySQL。
比较
第二个查询在Extra。
中另外提供了“Using filesort”答案 7 :(得分:3)
在 MySQL 中,“Group By
”使用额外的步骤:filesort
。我意识到DISTINCT
比GROUP BY
更快,这是一个惊喜。
答案 8 :(得分:2)
(更多功能性说明)
有些情况下您必须使用GROUP BY,例如,如果您想获得每个雇主的雇员人数:
SELECT u.employer, COUNT(u.id) AS "total employees" FROM users u GROUP BY u.employer
在这种情况下,DISTINCT u.employer
无法正常工作。也许有办法,但我只是不知道。 (如果有人知道如何使用DISTINCT进行此类查询,请添加注释!)
答案 9 :(得分: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.
答案 10 :(得分:1)
如果您不需要执行任何组功能(总和,平均值等,以防您想要向表中添加数值数据),请使用SELECT DISTINCT。我怀疑它更快,但我没有什么可以表现出来的。
在任何情况下,如果您担心速度,请在列上创建索引。
答案 11 :(得分:1)
经过大量测试后,我们得出结论,GROUP BY更快
SELECT sql_no_cache
opnamegroep_intern
来自telwerken
在opnemergroep
IN(7,8,9,10,11,12,13)组由opnamegroep_intern
635 totaal 0.0944秒 Weergave van记录0 - 29(635 totaal,查询duurde 0.0484 sec)
SELECT sql_no_cache
distinct(opnamegroep_intern)
来自telwerken
在opnemergroep
IN(7,8,9,10,11,12,13)
635 totaal 0.2117秒(差不多100%) Weergave van记录0 - 29(635 totaal,query duurde 0.3468 sec)
答案 12 :(得分:1)
这不是规则
对于每个查询....尝试单独区分然后分组...比较完成每个查询的时间并使用更快....
在我的项目中,有时候我会使用group by和其他不同的
答案 13 :(得分:0)
SELECT DISTINCT将始终与GROUP BY相同或更快。在某些系统(即Oracle)上,对于大多数查询,它可能被优化为与DISTINCT相同。在其他(例如SQL Server)上,它可以快得多。
答案 14 :(得分: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 )
这并非总是可行,但如果可用,您会看到更快的响应。