GROUP BY没有聚合函数

XFo*_*E07 60 sql oracle group-by aggregate-functions

我试图理解没有聚合函数的GROUP BY (新的oracle dbms).
它是如何运作的?
这是我尝试过的.

我将运行我的SQL的EMP表.
EMP表

SELECT ename , sal
FROM emp
GROUP BY ename , sal
Run Code Online (Sandbox Code Playgroud)

结果

SELECT ename , sal  
FROM emp  
GROUP BY ename;  
Run Code Online (Sandbox Code Playgroud)

结果

ORA-00979:不是GROUP BY表达式
00979. 00000 - "不是GROUP BY表达式"
*原因:
*操作:行
错误:397列:16

SELECT ename , sal  
FROM emp  
GROUP BY sal;  
Run Code Online (Sandbox Code Playgroud)

结果

ORA-00979:不是GROUP BY表达式
00979. 00000 - "不是GROUP BY表达式"
*原因:
*操作:行错误:411列:8

SELECT empno , ename , sal  
FROM emp  
GROUP BY sal , ename;  
Run Code Online (Sandbox Code Playgroud)

结果

ORA-00979:不是GROUP BY表达式
00979. 00000 - "不是GROUP BY表达式"
*原因:
*操作:行错误:425列:8

SELECT empno , ename , sal  
FROM emp  
GROUP BY empno , ename , sal;  
Run Code Online (Sandbox Code Playgroud)

结果

因此,基本上列的数量必须等于GROUP BY子句中的列数,但我仍然不明白为什么或发生了什么.

Tob*_*oth 88

这就是GROUP BY的工作方式.它需要几行并将它们变成一行.因此,它必须知道如何处理所有组合行,其中某些列(字段)具有不同的值.这就是为什么对于要SELECT的每个字段都有两个选项的原因:要么将它包含在GROUP BY子句中,要么在聚合函数中使用它,以便系统知道如何组合字段.

例如,假设你有这个表:

Name | OrderNumber
------------------
John | 1
John | 2
Run Code Online (Sandbox Code Playgroud)

如果你说GROUP BY Name,它将如何知道结果中显示哪个OrderNumber?因此,您要么在group by中包含OrderNumber,这将导致这两行.或者,您使用聚合函数来显示如何处理OrderNumbers.例如,MAX(OrderNumber)这意味着结果是John | 2SUM(OrderNumber)结果是John | 3.

  • 一个注意事项:您还可以拥有不在 GROUP BY 子句中的常量列。但确实所有列都必须属于以下三个类别之一:聚合函数、常量或必须出现在 GROUP BY 子句中。为清楚起见,当我说常量时,我​​的意思是“Select 1 sort_order FROM table1”之类的东西,您在实际 SQL 中分配常量值。 (2认同)

oer*_*ens 31

鉴于此数据:

Col1  Col2  Col3
 A     X     1
 A     Y     2
 A     Y     3
 B     X     0
 B     Y     3
 B     Z     1
Run Code Online (Sandbox Code Playgroud)

这个查询

SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2, Col3
Run Code Online (Sandbox Code Playgroud)

会产生完全相同的表格.

但是,这个查询:

SELECT Col1, Col2 FROM data GROUP BY Col1, Col2
Run Code Online (Sandbox Code Playgroud)

会导致

Col1  Col2
 A     X  
 A     Y  
 B     X  
 B     Y  
 B     Z  
Run Code Online (Sandbox Code Playgroud)

现在,查询:

SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2
Run Code Online (Sandbox Code Playgroud)

会产生问题:带有A,Y的行是将两行分组的结果

 A     Y     2
 A     Y     3
Run Code Online (Sandbox Code Playgroud)

那么,哪个值应该在Col3,'2'或'3'中?

通常你会使用group by计算一个总和:

SELECT Col1, Col2, SUM(Col3) FROM data GROUP BY Col1, Col2
Run Code Online (Sandbox Code Playgroud)

所以在我们遇到问题时,我们现在得到(2 + 3)= 5.

按选择中的所有列进行分组实际上与使用DISTINCT相同,在这种情况下最好使用DISTINCT关键字字可读性.

而不是

SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2, Col3
Run Code Online (Sandbox Code Playgroud)

使用

SELECT DINSTINCT Col1, Col2, Col3 FROM data
Run Code Online (Sandbox Code Playgroud)


Mis*_*Tom 22

您遇到了GROUP BY子句的严格要求.不在group-by子句中的每一列都必须应用一个函数来将匹配的"group"的所有记录减少到单个记录(sum,max,min等).

如果列出GROUP BY子句中的所有查询(选定)列,则实质上是要求从结果集中排除重复记录.这提供了与SELECT DISTINCT相同的效果,它也消除了结果集中的重复行.


Dav*_*dge 7

GROUP BY没有聚合的唯一真实用例是当GROUP BY列多于所选列时,在这种情况下可能会重复所选列.否则你不妨使用DISTINCT.

值得注意的是,其他RDBMS不要求所有非聚合列都包含在GROUP BY中.例如,在PostgreSQL中,如果表的主键列包含在GROUP BY中,那么该表的其他列不需要保证对于每个不同的主键列都是不同的.我曾经希望Oracle在许多情况下做的与更紧凑的SQL相同.


Sri*_*niV 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;
Run Code Online (Sandbox Code Playgroud)

现在表里有什么

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.
Run Code Online (Sandbox Code Playgroud)

--与分组聚合

SELECT
      VAL1,
      COUNT ( * )
FROM
      DATASET A
GROUP BY
      VAL1;

VAL1   COUNT(*)
---- ----------
b             1
a             2
c             2

3 rows selected.
Run Code Online (Sandbox Code Playgroud)

--aggregate with group by multiple columns 但选择部分列

SELECT
      VAL1,
      COUNT ( * )
FROM
      DATASET A
GROUP BY
      VAL1,
      VAL2;

VAL1  
---- 
b             
c             
a             
a             

4 rows selected.
Run Code Online (Sandbox Code Playgroud)

-- 没有按多列分组的聚合

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.
Run Code Online (Sandbox Code Playgroud)

-- 没有按多列分组的聚合

SELECT
      VAL1
FROM
      DATASET A
GROUP BY
      VAL1,
      VAL2;

    VAL1  
    ---- 
    b
    c
    a
    a

    4 rows selected.
Run Code Online (Sandbox Code Playgroud)

您在选择中有 N 列(不包括聚合),那么您应该有 N 或 N+x 列


ogr*_*res 3

如果 SELECT 子句中有一些列,如果有多行,它将如何选择它?所以是的,SELECT 子句中的每一列也应该在 GROUP BY 子句中,您可以在 SELECT 中使用聚合函数...

您可以在 GROUP BY 子句中包含不在 SELECT 子句中的列,但不能在其他情况下使用