13

GROUP BY 子句对行进行分组,但不一定按任何特定顺序对结果进行排序。要更改顺序,请使用 GROUP BY 子句之后的 ORDER BY 子句。ORDER BY 子句中使用的列必须出现在 SELECT 列表中,这与 ORDER BY 的正常使用不同。[Oracle 示例,第四版,第 274 页]

这是为什么?为什么使用 GROUP BY 会影响 SELECT 子句中所需的列?

此外,在我不使用 GROUP BY 的情况下:为什么我要对某些列进行排序,然后只选择列的一个子集?

4

7 回答 7

7

实际上,正如 Dave Costa 的例子所示,这种说法并不完全正确。

Oracle 文档说可以使用表达式,但表达式必须基于选择列表中的列。

expr - expr根据 expr 的值对行进行排序。该表达式基于选择列表中的列或 FROM 子句中的表、视图或实例化视图中的列。来源:Oracle® 数据库 SQL 语言参考 11g 第 2 版 (11.2) E26088-01 September 2011。第 19-33 页

来自同一工作页面 19-13 和 19-33(PDF 中的第 1355 和 1365 页)

在此处输入图像描述

在此处输入图像描述

http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10002.htm#SQLRF01702

http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_10002.htm#i2171079

于 2012-08-29T18:51:32.957 回答
7

您报价中的粗体文本不正确(在许多常见用例中这可能是一种过度简化,但严格来说,这并不是一个要求)。例如,这个语句执行得很好,虽然AVG(val)不在选择列表中:

WITH DATA AS (SELECT mod(LEVEL,3) grp, LEVEL val FROM dual CONNECT BY LEVEL < 100)
SELECT grp,MIN(val),MAX(val)
FROM DATA
GROUP BY grp
ORDER BY AVG(val)

ORDER BY 子句中的表达式必须能够在 GROUP BY 的上下文中进行计算。例如,ORDER BY val在上面的示例中不起作用,因为表达式val对于分组产生的每一行没有不同的值。

至于你的第二个问题,你可能关心排序但不关心排序表达式的值。从选择列表中排除不需要的表达式可以减少实际上必须从服务器发送到客户端的数据量。

于 2012-08-29T18:56:14.840 回答
3

第一的:

group by 的实现是创建一个在结构上与原始 from 子句(表视图或某些连接表)不同的新结果集。该结果集由所选内容定义。

并非每个 SQL RDBMS 都有此限制,尽管始终要求排序的内容是非分组列( 、 等)的聚合函数AVG或分组SUM的列之一,或基于多个列的函数那些结果(比如添加两列),因为这是分组操作结果的逻辑要求。

第二:

因为您只关心该列的排序。例如,您可能有一个最畅销单曲的列表,但没有给出他们的销量(《纽约时报》畅销书对其数据的一些细节保密,但确实有一个排名列表)。当然,您可以通过选择该列然后不使用它来解决此问题。

于 2012-08-29T18:59:38.060 回答
2

数据在按 ORDER BY 排序之前进行聚合。

如果您尝试按任何其他列(不在 group by 列表或聚合函数中)排序,将使用什么值?没有用于排序的单一值。

我相信您可以使用值的组合进行排序。所以你可以说:

order by a+b

如果 a 和 b 在 group by 中。您只是不能引入 SELECT 中未提及的列。但是,我相信您可以使用 SELECT 中未提及的聚合函数。

于 2012-08-29T18:54:12.067 回答
1

样品表

sample.grades
Name   Grade    Score
Adam   A        95
Bob    A        97
Charlie C       75

使用 GROUP BY 的第一个查询

Select grade, count(Grade) from sample.grades GROUP BY Grade

输出

Grade Count
A     2
C     1

使用 order by 的第二个查询

select Name, score from sample grades order by score

输出

Bob    A        97
Adam   A        95
Charlie C       75

使用 GROUP BY 和排序的第三个查询

Select grade, count(Grade) from sample.grades GROUP BY Grade desc

输出

Grade Count
A     2
C     1

一旦你开始使用像 Count 这样的东西,你必须有 group by。您可以将它们一起使用,但它们有非常不同的用途,我希望这些示例清楚地表明了这一点。

为了尝试回答这个问题,为什么 group by 会影响 select 部分中的项目,因为这就是 group by 的目的。如果您不按该列分组,则无法对列进行计数。

第二个问题,为什么要排序但不选择所有列?如果我想按分数排序,但不关心实际成绩甚至我可能会做的分数

select name from sample.grades order by score

输出

Name
Bob
Adam
Charlie
于 2012-08-29T18:52:44.207 回答
0

您希望看到哪些结果按未列在选择列表中且未参与 group by 子句的列排序?在任何情况下,SELECT 列表列中未提及的所有排序方式都将被省略,因此 Oracle 人员正确添加了限制。

with c as (
select 1 id, 2 value from dual
union all
select 1 id, 3 value from dual
union all
select 2 id, 3 value from dual
)
select id
from c
group by id
order by count(*) desc
于 2012-08-29T18:52:12.673 回答
0

这里是我的理解

“GROUP BY 子句对行进行分组,但不一定按任何特定顺序对结果进行排序。”

-> 您可以使用 Group by 而无需 order by

“要更改顺序,请使用 GROUP BY 子句之后的 ORDER BY 子句。”

-> 行由默认主键选择,如果添加 order by 则必须在 group by 之后添加

“ORDER BY 子句中使用的列必须出现在 SELECT 列表中,这与 ORDER BY 的正常使用不同。”

于 2012-08-29T18:52:56.980 回答