SELECT 列如何不在 GROUP BY 子句中列出

-1 group-by sql-standard

查询:

select year,sum(mark),sum(maxmark) 
from table1 
group by parameterno
Run Code Online (Sandbox Code Playgroud)

产生错误消息:

列“table1.year”在选择列表中无效,因为它不包含在聚合函数或 GROUP BY 子句中。

Tom*_*m V 10

如果不将字段包含在分组依据列表中,则无法跨字段选择聚合。

如果你想要每年的总数,你应该写

SELECT year,sum(mark),sum(maxmark) 
FROM table1 
GROUP BY year
Run Code Online (Sandbox Code Playgroud)

如果你想要每个参数的总数,它应该是

SELECT parameterno,sum(mark),sum(maxmark) 
FROM table1 
GROUP BY parameterno
Run Code Online (Sandbox Code Playgroud)

从错误消息我猜你正在使用 SQL Server 所以看看文档


Len*_*art 10

我不清楚你在问什么,但我相信这GROUP BY是 中最容易被误解的概念之一SQL,所以无论如何我都会添加这个答案。它可能有助于也可能不会帮助理解这个概念GROUP BY。假设我们有一个表格:

CREATE TABLE T
( YEAR INT NOT NULL
, PARAMETERNO INT NOT NULL
, MARK INT NOT NULL
, PRIMARY KEY (YEAR, PARAMETERNO) );

INSERT INTO T ( YEAR, PARAMETERNO, MARK )
VALUES (2014,1,10),(2014,2,20),(2015,1,15),(2015,2,25);
Run Code Online (Sandbox Code Playgroud)

什么会:

SELECT YEAR, SUM(MARK)
FROM T
GROUP BY PARAMETERNO
Run Code Online (Sandbox Code Playgroud)

意思?按 PARAMETERNO 分组意味着我们有两个组

1    2014    10
     2015    20
2    2014    15
     2015    25
Run Code Online (Sandbox Code Playgroud)

我们应用了聚合函数 SUM,但是 YEAR 是如何发挥作用的呢?这可能意味着:

     2014    30  -- 10+20 in group 1
     2015    30
     2014    40  -- 15+25 in group 2
     2015    40
Run Code Online (Sandbox Code Playgroud)

但这几乎不是一个有用的结果?另一种可能性是从每组中随机选择一行,例如:

     2014    30  -- 10+20 in group 1
     2015    40  -- 15+25 in group 2
Run Code Online (Sandbox Code Playgroud)

结果是不可预测的,对于相同的数据/查询,您可能会得到不同的结果。

SQL92 要求 中的所有列SELECT CLAUSE都是 的一部分GROUP BY CLAUSE,所以如果我们想要:

SELECT YEAR, SUM(MARK)
FROM T
Run Code Online (Sandbox Code Playgroud)

我们必须至少添加 YEAR 到GROUP BY

SELECT YEAR, SUM(MARK)
FROM T
GROUP BY YEAR 
Run Code Online (Sandbox Code Playgroud)

(可以添加其他列,虽然不是很常见)。结果:

     2014    25 -- 10+15 in group 2014
     2015    45 -- 20+25 in group 2015
Run Code Online (Sandbox Code Playgroud)

SQL99 放宽了这一限制,并要求SELECT子句中的所有列在功能上都由该GROUP BY子句确定(不是数据本身,而是声明的约束)。在一个表的微不足道的情况下,这意味着如果GROUP BY子句唯一标识一行,我们可以向SELECT子句添加我们想要的任何列。例子:

CREATE TABLE T
( YEAR INT NOT NULL
, PARAMETERNO INT NOT NULL
, MARK INT NOT NULL
, PRIMARY KEY (YEAR) );

INSERT INTO T ( YEAR, PARAMETERNO, MARK )
VALUES (2014,1,10),(2015,2,20),(2016,1,15),(2017,2,25);
Run Code Online (Sandbox Code Playgroud)

现在,因为PARAMETERNO在功能上由YEAR以下查询确定:

SELECT YEAR, PARAMETERNO, SUM(MARK)
FROM T
GROUP BY YEAR 
Run Code Online (Sandbox Code Playgroud)

将是有效的。AFAIK 知道最新版本PostgreSQL并且MySQL是唯一实现GROUP BY.

对于那些未实现 SQL99 版本的 DBMS 的一个技巧是将聚合应用于这些列:

SELECT YEAR, MAX(PARAMETERNO), SUM(MARK)
FROM T
GROUP BY YEAR 
Run Code Online (Sandbox Code Playgroud)

由于每年只有一个 PARAMETERNO,因此结果是相同的。

MySQL 历史上允许您违反 SQL92 和 SQL99GROUP BY规则,除非您在@@sql_mode 中指定 ONLY_FULL_GROUP_BY。这可能会导致不确定的结果,并且多年来在诸如此类的论坛中引起了很多混乱。我个人总是将@@sql_mode 设置为 ONLY_FULL_GROUP_BY 在使用比最新版本(我还没有尝试过)更旧的 MySQL 版本时。