GROUP BY 子句对行进行分组,但不一定按任何特定顺序对结果进行排序。要更改顺序,请使用 GROUP BY 子句之后的 ORDER BY 子句。ORDER BY 子句中使用的列必须出现在 SELECT 列表中,这与 ORDER BY 的正常使用不同。[Oracle 示例,第四版,第 274 页]
这是为什么?为什么使用 GROUP BY 会影响 SELECT 子句中所需的列?
此外,在我不使用 GROUP BY 的情况下:为什么我要对某些列进行排序,然后只选择列的一个子集?
GROUP BY 子句对行进行分组,但不一定按任何特定顺序对结果进行排序。要更改顺序,请使用 GROUP BY 子句之后的 ORDER BY 子句。ORDER BY 子句中使用的列必须出现在 SELECT 列表中,这与 ORDER BY 的正常使用不同。[Oracle 示例,第四版,第 274 页]
这是为什么?为什么使用 GROUP BY 会影响 SELECT 子句中所需的列?
此外,在我不使用 GROUP BY 的情况下:为什么我要对某些列进行排序,然后只选择列的一个子集?
实际上,正如 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
您报价中的粗体文本不正确(在许多常见用例中这可能是一种过度简化,但严格来说,这并不是一个要求)。例如,这个语句执行得很好,虽然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
对于分组产生的每一行没有不同的值。
至于你的第二个问题,你可能关心排序但不关心排序表达式的值。从选择列表中排除不需要的表达式可以减少实际上必须从服务器发送到客户端的数据量。
第一的:
group by 的实现是创建一个在结构上与原始 from 子句(表视图或某些连接表)不同的新结果集。该结果集由所选内容定义。
并非每个 SQL RDBMS 都有此限制,尽管始终要求排序的内容是非分组列( 、 等)的聚合函数AVG
或分组SUM
的列之一,或基于多个列的函数那些结果(比如添加两列),因为这是分组操作结果的逻辑要求。
第二:
因为您只关心该列的排序。例如,您可能有一个最畅销单曲的列表,但没有给出他们的销量(《纽约时报》畅销书对其数据的一些细节保密,但确实有一个排名列表)。当然,您可以通过选择该列然后不使用它来解决此问题。
数据在按 ORDER BY 排序之前进行聚合。
如果您尝试按任何其他列(不在 group by 列表或聚合函数中)排序,将使用什么值?没有用于排序的单一值。
我相信您可以使用值的组合进行排序。所以你可以说:
order by a+b
如果 a 和 b 在 group by 中。您只是不能引入 SELECT 中未提及的列。但是,我相信您可以使用 SELECT 中未提及的聚合函数。
样品表
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
您希望看到哪些结果按未列在选择列表中且未参与 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
这里是我的理解
“GROUP BY 子句对行进行分组,但不一定按任何特定顺序对结果进行排序。”
-> 您可以使用 Group by 而无需 order by
“要更改顺序,请使用 GROUP BY 子句之后的 ORDER BY 子句。”
-> 行由默认主键选择,如果添加 order by 则必须在 group by 之后添加
“ORDER BY 子句中使用的列必须出现在 SELECT 列表中,这与 ORDER BY 的正常使用不同。”