sql group by 与 distinct

Posted

技术标签:

【中文标题】sql group by 与 distinct【英文标题】:sql group by versus distinct 【发布时间】:2010-09-30 09:58:15 【问题描述】:

当查询中没有进行聚合时,为什么有人会使用 group by 而不是 distinct?

此外,是否有人通过 mysql 和 SQL Server 中的不同性能考虑来了解该组。我猜 SQL Server 有一个更好的优化器,它们可能与那里相当,但在 MySQL 中,我预计会有明显的性能优势。

我对 dba 的答案很感兴趣。

编辑:

Bill 的帖子很有趣,但不适用。让我更具体一点...

select a, b, c 
from table x
group by a, b,c

select distinct a,b,c
from table x

【问题讨论】:

这与***.com/questions/164319/… 的问题密切相关,但并不完全相同 很可能是因为他们不知道自己在做什么。如果您确定他们知道他们在做什么,那么我会怀疑两者之间处理 NULL 值的方式有所不同——不过,我想不出是什么。 我认为答案很简单——作者不知道 distinct(这令人惊讶,因为我认为他是专业人士)。 【参考方案1】:

两者都会在 MS SQL Server 中生成相同的查询计划...。如果您有 MS SQL Server,您只需启用实际执行计划,看看哪个更适合您的需求...

请查看这些帖子:

http://blog.sqlauthority.com/2007/03/29/sql-server-difference-between-distinct-and-group-by-distinct-vs-group-by/

http://www.sqlmag.com/Article/ArticleID/24282/sql_server_24282.html

【讨论】:

使用 group by 而不是像 newb 这样的独特气味。有更多的语法没有收获。另外 - 你没有任何指标 - 只是来自别人博客的传闻。【参考方案2】:

GROUP BY 将行组映射到一行,根据特定列中的不同值,这些列甚至不一定必须在选择列表中。

SELECT b, c, d FROM table1 GROUP BY a;

这个查询是合法的SQL(更正:只在MySQL中;实际上它不是标准SQL,其他品牌不支持)。 MySQL 接受它,它相信您知道自己在做什么,以明确的方式选择 bcd,因为它们是 functional dependencies 和 a

但是,Microsoft SQL Server 和其他品牌不允许这种查询,因为它不能轻易确定函数依赖关系。 编辑: 相反,标准 SQL 要求您遵循 单值规则,即选择列表中的每一列必须在 GROUP BY 子句中命名,否则成为集合函数的参数。

DISTINCT 总是查看选择列表中的所有列,并且只查看那些列。 DISTINCT 允许您指定列是一个常见的误解:

SELECT DISTINCT(a), b, c FROM table1;

尽管括号使DISTINCT 看起来像函数调用,但事实并非如此。这是一个查询选项,选择列表的三个字段中的任何一个字段中的不同值都将导致查询结果中的不同行。此选择列表中的表达式之一有括号,但这不会影响结果。

【讨论】:

有趣但无关紧要。您正在回答有关在查询中出错的问题。另外,我认为接受您提出的此类查询不是 ansi 标准。如果有的话,那是 mysql 中的一个错误——其他主要供应商不支持这个“功能” 跑题了,但 Bill 给出的第二个查询 (SELECT DISTINCT(a)...) 是完全有效的 ANSI SQL-92。括号实际上是无关紧要的;您可以执行 SELECT a, (b), c FROM table1,这是有效的。只是因为它是第一个参数,所以它看起来像“a”是 DISTINCT 的参数。 @mson:你是对的!我在我的“SQL-99 Complete, really”中查找了它,它说执行单值规则是标准 SQL,而不执行它的 RDBMS(例如 MySQL)不符合标准 SQL。 @Cowan:是的,这就是我的观点。它是有效的语法,它完全按照它应该做的那样做,但这与某些人认为的不同。 FWIW,SQLite 也不强制执行单值规则。此外,如果您设置ONLY_FULL_GROUP_BY SQL 模式,MySQL 将强制执行该规则。【参考方案3】:

如果你真的在寻找不同的值,不同的值会使源代码更具可读性(就像它是存储过程的一部分)如果我正在编写临时查询,我通常会从 group by 开始,甚至如果我没有聚合,因为我经常会添加它们。

【讨论】:

我做的和你做的一样,但是方向相反。我从 select distinct 开始,如果有理由,我会转到 group by。我不会尝试优化一切,但如果我能记住一些关于什么是更快和更清洁的经验法则,我会遵循它们。 group by 有点乱-2 子句【参考方案4】:

来自 MS SQL Server 的少量(非常少)经验数据,来自我们数据库中的几个随机表。

对于模式:

SELECT col1, col2 FROM table GROUP BY col1, col2

SELECT DISTINCT col1, col2 FROM table 

当查询没有覆盖索引时,两种方式都会产生以下查询计划:

|--Sort(DISTINCT ORDER BY:([table].[col1] ASC, [table].[col2] ASC))
   |--Clustered Index Scan(OBJECT:([db].[dbo].[table].[IX_some_index]))

当有覆盖索引时,两者都产生:

|--Stream Aggregate(GROUP BY:([table].[col1], [table].[col2]))
   |--Index Scan(OBJECT:([db].[dbo].[table].[IX_some_index]), ORDERED FORWARD)

因此,从这个非常小的示例中,SQL Server 肯定会同等对待两者。

【讨论】:

感谢您的确认——我猜大供应商已经对此进行了优化,但我也猜 MySQL 没有。【参考方案5】:

在 MySQL 中,我发现使用 GROUP BY 的性能通常比 DISTINCT 更好。

执行“EXPLAIN SELECT DISTINCT”会显示“Using where; Using temporary” MySQL 将创建一个临时表。

vs a "EXPLAIN SELECT a,b, c from T1, T2 where T2.A=T1.A GROUP BY a" 只显示 "Using where"

【讨论】:

您始终应该检查相关查询的解释。今天我有一个查询,它是“使用临时;使用文件排序”和 group by,但只有“使用临时”和 DISTINCT。因此 DISTINCT 变体快 4 倍。 (mysql 5.7)

以上是关于sql group by 与 distinct的主要内容,如果未能解决你的问题,请参考以下文章

T-SQL-Sum over Partition by 与 group by 组合

SQL compute by 的使用 主要是针对与 GROUP BY 的区别

order by 与group by 啥意思啊,数据库高手看看

sql计算平均值与group by?

与 sql_mode=only_full_group_by 不兼容的 MySQL 查询

SQL GROUP BY 语句与实战例题