Tar*_*aal 20 sql aggregate-functions
我知道如果在SELECT语句中有一个聚合函数,那么语句中的所有其他值必须是聚合函数,或者在GROUP BY子句中列出.我不明白为什么会这样.
如果我做:
SELECT Name, 'Jones' AS Surname FROM People
Run Code Online (Sandbox Code Playgroud)
我明白了:
NAME SURNAME
Dave Jones
Susan Jones
Amy Jones
Run Code Online (Sandbox Code Playgroud)
因此,DBMS从每一行获取一个值,并在结果集中为其附加一个值.没关系.但如果可行的话,我为什么不能这样做:
SELECT Name, COUNT(Name) AS Surname FROM People
Run Code Online (Sandbox Code Playgroud)
看起来是一样的想法,从每一行中取一个值并附加一个值.而不是:
NAME SURNAME
Dave 3
Susan 3
Amy 3
Run Code Online (Sandbox Code Playgroud)
我明白了:
您尝试执行不包含指定表达式"ContactName"的查询作为聚合函数的一部分.
我知道这是不允许的,但这两种情况看起来很相似,我不明白为什么.是否使DBMS更容易实现?如果有人能向我解释为什么它不能像我认为的那样起作用,我将非常感激.
Guf*_*ffa 17
聚合不适用于完整结果,它们仅适用于结果中的组.
考虑一个表包含:
Person Pet
-------- --------
Amy Cat
Amy Dog
Amy Canary
Dave Dog
Susan Snake
Susan Spider
Run Code Online (Sandbox Code Playgroud)
如果您使用在Person上分组的查询,它会将数据划分为以下组:
Amy:
Amy Cat
Amy Dog
Amy Canary
Dave:
Dave Dog
Susan:
Susan Snake
Susan Spider
Run Code Online (Sandbox Code Playgroud)
如果您使用aggreage,例如计数聚合,它将为每个组生成一个结果:
Amy:
Amy Cat
Amy Dog
Amy Canary count(*) = 3
Dave:
Dave Dog count(*) = 1
Susan:
Susan Snake
Susan Spider count(*) = 2
Run Code Online (Sandbox Code Playgroud)
因此,查询select Person, count(*) from People group by Person为您提供每个组的一条记录:
Amy 3
Dave 1
Susan 2
Run Code Online (Sandbox Code Playgroud)
如果您尝试在结果中获取Pet字段,那么这不起作用,因为每个组中该字段可能有多个值.
(有些数据库,比如MySQL,确实允许这样做,只返回组内的任何随机值,你有责任知道结果是否合理.)
如果您使用聚合但未指定任何分组,则仍将对查询进行分组,并且整个结果为单个组.因此,查询select count(*) from Person将创建包含所有记录的单个组,并且聚合可以计算该组中的记录.结果包含每个组中的一行,并且由于只有一个组,因此结果中将有一行.
可以这样考虑一下:当你在没有分组的情况下调用COUNT时,它会将表"折叠"到一个组中,从而无法访问select子句中组内的各个项目.
您仍然可以使用子查询或交叉连接获得结果:
SELECT p1.Name, COUNT(p2.Name) AS Surname FROM People p1 CROSS JOIN People p2 GROUP BY p1.Name
SELECT Name, (SELECT COUNT(Name) FROM People) AS Surname FROM People
Run Code Online (Sandbox Code Playgroud)
正如其他人解释说,当你有一个GROUP BY,或者你使用的是聚合函数一样COUNT()在SELECT列表中,你正在做行的分组,因此崩溃匹配的行成一个为每个组.
当您仅在SELECT列表中使用聚合函数时,请不要GROUP BY将其视为具有GROUP BY 1,因此将所有行分组,折叠为一个.所以,如果你有一百行,数据库就无法真正显示你的名字,因为它们有一百个.
但是,对于具有"窗口"功能的RDBMS,您想要的是可行的.例如,使用聚合函数而不使用GROUP BY.
SQL-Server的示例,其中计算表中的所有行(名称):
SELECT Name
, COUNT(*) OVER() AS cnt
FROM People
Run Code Online (Sandbox Code Playgroud)
以上是如何工作的?
它显示了Name像
COUNT(*) OVER() AS cnt并不存在,
COUNT(*)如果它正在对表格进行总分组,则会显示相似内容.
另一个例子.如果Surname表上有一个字段,您可以使用这样的字段显示按姓氏分组的所有行,并计算有多少人具有相同的姓氏:
SELECT Name
, Surname
, COUNT(*) OVER(PARTITION BY Surname) AS cnt
FROM People
Run Code Online (Sandbox Code Playgroud)