没有聚合函数的 GROUP BY
Posted
技术标签:
【中文标题】没有聚合函数的 GROUP BY【英文标题】:GROUP BY without aggregate function 【发布时间】:2013-12-03 04:24:34 【问题描述】:我正在尝试理解 (oracle dbms 的新手)。 它是如何运作的? 这是我尝试过的。
我将在其上运行 SQL 的 EMP 表。
SELECT ename , sal
FROM emp
GROUP BY ename , sal
SELECT ename , sal
FROM emp
GROUP BY ename;
结果
ORA-00979:不是 GROUP BY 表达式 00979. 00000 - “不是 GROUP BY 表达式” *原因: *行动: 行错误:397 列:16
SELECT ename , sal
FROM emp
GROUP BY sal;
结果
ORA-00979:不是 GROUP BY 表达式 00979. 00000 - “不是 GROUP BY 表达式” *原因: *操作:行错误:411 列:8
SELECT empno , ename , sal
FROM emp
GROUP BY sal , ename;
结果
ORA-00979:不是 GROUP BY 表达式 00979. 00000 - “不是 GROUP BY 表达式” *原因: *操作:行错误:425 列:8
SELECT empno , ename , sal
FROM emp
GROUP BY empno , ename , sal;
所以,基本上列数必须等于 GROUP BY 子句中的列数,但我仍然不明白为什么或发生了什么。
【问题讨论】:
如果没有聚合函数并且您不介意按升序或降序获取结果,则可以改用排序 (ORDER BY)。 功能上,如果你在选择中使用,你只是在做一个 DISTINCT。 Oracle 似乎对每种方法都使用了不同的方法,但结果却是相同的。 【参考方案1】:这就是 GROUP BY 的工作原理。它需要几行并将它们变成一行。因此,它必须知道如何处理某些列(字段)具有不同值的所有组合行。这就是为什么对于要 SELECT 的每个字段都有两个选项:要么将其包含在 GROUP BY 子句中,要么在聚合函数中使用它,以便系统知道您要如何组合字段。
例如,假设您有这张桌子:
Name | OrderNumber
------------------
John | 1
John | 2
如果您说 GROUP BY Name,它如何知道要在结果中显示哪个 OrderNumber?因此,您可以在 group by 中包含 OrderNumber,这将导致这两行。或者,您使用聚合函数来展示如何处理 OrderNumber。例如MAX(OrderNumber)
,表示结果为John | 2
或SUM(OrderNumber)
,表示结果为John | 3
。
【讨论】:
注意:您还可以拥有不在 GROUP BY 子句中的常量列。但确实所有列都必须属于以下三个类别之一:聚合函数、常量,或者它必须出现在 GROUP BY 子句中。为清楚起见,当我说常量时,我的意思是“从 table1 中选择 1 个排序顺序”,您在实际 SQL 中分配一个常量值。 正如@Varun 所说,¡ 有史以来最好的解释!帮助我简单地理解GROUP BY
、ORDER BY
和聚合函数会发生什么。简单地说,克莱尔,举一个非常简单的例子。 ¡ 非常感谢!【参考方案2】:
鉴于此数据:
Col1 Col2 Col3
A X 1
A Y 2
A Y 3
B X 0
B Y 3
B Z 1
这个查询:
SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2, Col3
将产生完全相同的表。
但是,这个查询:
SELECT Col1, Col2 FROM data GROUP BY Col1, Col2
会导致:
Col1 Col2
A X
A Y
B X
B Y
B Z
现在,一个查询:
SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2
会产生一个问题:带有A,Y的行是两行分组的结果
A Y 2
A Y 3
那么,Col3 中的值应该是 '2' 还是 '3'?
通常您会使用GROUP BY
来计算,例如一笔:
SELECT Col1, Col2, SUM(Col3) FROM data GROUP BY Col1, Col2
所以在这条线上,我们遇到了一个问题,我们现在得到 (2+3) = 5。
在您的选择中按所有列分组实际上与使用 DISTINCT 相同,在这种情况下最好使用 DISTINCT 关键字词的可读性。
所以不是
SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2, Col3
使用
SELECT DISTINCT Col1, Col2, Col3 FROM data
【讨论】:
SELECT Col1, Col2, Col3 FROM data GROUP BY Col1
会产生什么结果?
@SantanuSur 这只会产生我为SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2
解释的相同问题,但有一个额外的问题列。对于 Col1
= A 的行,您希望 Col2
和 Col3
的值是多少?
我只想group the data
一栏
假设我有一个包含 3 列的表...并且第三列有许多重复项..我想提取该表...没有第三列变得混乱...示例第 3 列:- A B A B
我想获得所有具有第 3 列结果的列,如下所示:- A A B B
select * from table group by 3rd Column
会起作用吗??【参考方案3】:
您遇到了 GROUP BY 子句的严格要求。不在 group-by 子句中的每一列都必须应用一个函数来将匹配“组”的所有记录减少为单个记录(sum、max、min 等)。
如果您在 GROUP BY 子句中列出所有查询(选择)的列,您实际上是在请求从结果集中排除重复记录。这提供了与 SELECT DISTINCT 相同的效果,后者还从结果集中消除了重复的行。
【讨论】:
【参考方案4】:没有聚合的 GROUP BY 唯一真正的用例是当您 GROUP BY 的列多于选定的列时,在这种情况下,选定的列可能会重复。否则,您不妨使用 DISTINCT。
值得注意的是,其他 RDBMS 并不要求所有非聚合列都包含在 GROUP BY 中。例如,在 PostgreSQL 中,如果表的主键列包含在 GROUP BY 中,则该表的其他列不需要,因为它们保证对于每个不同的主键列都是不同的。过去,我希望 Oracle 能像在许多情况下为更紧凑的 SQL 所做的那样做同样的事情。
【讨论】:
【参考方案5】:让我举几个例子。
考虑这些数据。
CREATE TABLE DATASET ( VAL1 CHAR ( 1 CHAR ),
VAL2 VARCHAR2 ( 10 CHAR ),
VAL3 NUMBER );
INSERT INTO
DATASET ( VAL1, VAL2, VAL3 )
VALUES
( 'b', 'b-details', 2 );
INSERT INTO
DATASET ( VAL1, VAL2, VAL3 )
VALUES
( 'a', 'a-details', 1 );
INSERT INTO
DATASET ( VAL1, VAL2, VAL3 )
VALUES
( 'c', 'c-details', 3 );
INSERT INTO
DATASET ( VAL1, VAL2, VAL3 )
VALUES
( 'a', 'dup', 4 );
INSERT INTO
DATASET ( VAL1, VAL2, VAL3 )
VALUES
( 'c', 'c-details', 5 );
COMMIT;
现在桌子上有什么
SELECT * FROM DATASET;
VAL1 VAL2 VAL3
---- ---------- ----------
b b-details 2
a a-details 1
c c-details 3
a dup 4
c c-details 5
5 rows selected.
--与分组聚合
SELECT
VAL1,
COUNT ( * )
FROM
DATASET A
GROUP BY
VAL1;
VAL1 COUNT(*)
---- ----------
b 1
a 2
c 2
3 rows selected.
--按多列聚合,但选择部分列
SELECT
VAL1,
COUNT ( * )
FROM
DATASET A
GROUP BY
VAL1,
VAL2;
VAL1
----
b
c
a
a
4 rows selected.
--没有按多列分组的聚合
SELECT
VAL1,
VAL2
FROM
DATASET A
GROUP BY
VAL1,
VAL2;
VAL1
----
b b-details
c c-details
a dup
a a-details
4 rows selected.
--没有按多列分组的聚合
SELECT
VAL1
FROM
DATASET A
GROUP BY
VAL1,
VAL2;
VAL1
----
b
c
a
a
4 rows selected.
您在选择中有 N 列(不包括聚合),那么您应该有 N 或 N+x 列
【讨论】:
【参考方案6】:使用子查询例如:
SELECT field1,field2,(SELECT distinct field3 FROM tbl2 WHERE criteria) AS field3
FROM tbl1 GROUP BY field1,field2
或
SELECT DISTINCT field1,field2,(SELECT distinct field3 FROM tbl2 WHERE criteria) AS field3
FROM tbl1
【讨论】:
【参考方案7】:如果 SELECT 子句中有一些列,如果有几行,它将如何选择它?所以是的,SELECT 子句中的每一列也应该在 GROUP BY 子句中,您可以在 SELECT 中使用聚合函数...
您可以在 GROUP BY 子句中包含不在 SELECT 子句中的列,但不能在其他情况下
【讨论】:
【参考方案8】:作为补充
基本上列数必须等于 GROUP BY 子句中的列数
不是一个正确的说法。
任何不属于 GROUP BY 子句的属性都不能用于选择 任何属于 GROUP BY 子句的属性都可以用于选择,但不是强制性的。【讨论】:
【参考方案9】:我知道你说过如果你有这样的数据你想了解 group by:
COL-A COL-B COL-C COL-D
1 Ac C1 D1
2 Bd C2 D2
3 Ba C1 D3
4 Ab C1 D4
5 C C2 D5
你想让数据看起来像:
COL-A COL-B COL-C COL-D
4 Ab C1 D4
1 Ac C1 D1
3 Ba C1 D3
2 Bd C2 D2
5 C C2 D5
你使用:
select * from table_name
order by col-c,colb
因为我认为这是你打算做的。
【讨论】:
以上是关于没有聚合函数的 GROUP BY的主要内容,如果未能解决你的问题,请参考以下文章
得到 ORA-00979: 不是没有任何聚合函数的 GROUP BY 语句
为啥没有聚合函数的选择列需要成为 MySQL 中 Group by 子句的一部分?