GROUP BY没有聚合函数

时间:2013-11-19 14:46:17

标签: sql oracle group-by aggregate-functions

我正在尝试理解没有聚合功能的GROUP BY (oracle dbms新手)
它是如何运作的?
这是我尝试过的。

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

SELECT ename , sal
FROM emp
GROUP BY ename , sal

Result

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;  

Result

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

9 个答案:

答案 0 :(得分:86)

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

例如,假设你有这张表:

Name | OrderNumber
------------------
John | 1
John | 2

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

答案 1 :(得分:23)

鉴于此数据:

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。

您在select中的所有列进行分组与使用DISTINCT实际上相同,在这种情况下最好使用DISTINCT关键字的单词可读性。

所以而不是

SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2, Col3

使用

SELECT DINSTINCT Col1, Col2, Col3 FROM data

答案 2 :(得分:20)

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

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

答案 3 :(得分:7)

GROUP BY没有聚合的唯一真实用例是当GROUP BY列数超过所选列时,在这种情况下可能会重复所选列。否则你也可以使用DISTINCT。

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

答案 4 :(得分:4)

让我举几个例子。

考虑这些数据。

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列

答案 5 :(得分:3)

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

中使用聚合函数

你可以在GROUP BY子句中使用不在SELECT子句中的列,但不能

答案 6 :(得分:2)

使用子查询,例如:

SELECT field1,field2,(SELECT distinct field3 FROM tbl2 WHERE criteria) AS field3
FROM tbl1 GROUP BY field1,field2

OR

SELECT DISTINCT field1,field2,(SELECT distinct field3 FROM tbl2 WHERE criteria) AS field3
FROM tbl1

答案 7 :(得分:1)

作为补充

  

基本上列数必须等于GROUP BY子句中的列数

不是正确的陈述。

  • 任何不属于GROUP BY子句的属性都不能用于选择
  • 作为GROUP BY子句一部分的任何属性都可用于选择但不是必需的。

答案 8 :(得分:0)

我知道你说如果你有这样的数据你想要了解分组:

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

因为我认为这是你打算做的事。