GROUP BY ohne Aggregatfunktion

72

Ich versuche, GROUP BY (neu in Oracle DBMS) ohne Aggregatfunktion zu verstehen .
Wie funktioniert es?
Folgendes habe ich versucht.

EMP-Tabelle, auf der ich mein SQL ausführen werde.
EMP-TABELLE

SELECT ename , sal
FROM emp
GROUP BY ename , sal

Ergebnis

SELECT ename , sal  
FROM emp  
GROUP BY ename;  

Ergebnis

ORA-00979: kein GROUP BY-Ausdruck
00979. 00000 - "kein GROUP BY-Ausdruck"
* Ursache:
* Maßnahme:
Fehler in Zeile: 397 Spalte: 16

SELECT ename , sal  
FROM emp  
GROUP BY sal;  

Ergebnis

ORA-00979: kein GROUP BY-Ausdruck
00979. 00000 - "kein GROUP BY-Ausdruck"
* Ursache:
* Maßnahme: Fehler in Zeile: 411 Spalte: 8

SELECT empno , ename , sal  
FROM emp  
GROUP BY sal , ename;  

Ergebnis

ORA-00979: kein GROUP BY-Ausdruck
00979. 00000 - "kein GROUP BY-Ausdruck"
* Ursache:
* Maßnahme: Fehler in Zeile: 425 Spalte: 8

SELECT empno , ename , sal  
FROM emp  
GROUP BY empno , ename , sal;  

Ergebnis

Grundsätzlich muss die Anzahl der Spalten der Anzahl der Spalten in der GROUP BY-Klausel entsprechen, aber ich verstehe immer noch nicht, warum oder was los ist.

XForCE07
quelle
Wenn es keine Aggregatfunktion gibt und es Ihnen nichts ausmacht, das Ergebnis in aufsteigender oder absteigender Reihenfolge zu erhalten, können Sie stattdessen die Sortierung verwenden ( ORDER BY ).
Bhaskar
7
Wenn Sie GROUP BY ohne Aggregatfunktionen in der Auswahl verwenden, führen Sie funktional nur ein DISTINCT aus. Oracle scheint für jede Methode unterschiedliche Methoden zu verwenden, endet jedoch mit demselben Ergebnis.
ZeroK

Antworten:

108

So funktioniert GROUP BY. Es dauert mehrere Reihen und macht sie zu einer Reihe. Aus diesem Grund muss es wissen, was mit allen kombinierten Zeilen zu tun ist, in denen es für einige Spalten (Felder) unterschiedliche Werte gibt. Aus diesem Grund haben Sie zwei Optionen für jedes Feld, das Sie AUSWÄHLEN möchten: Fügen Sie es entweder in die GROUP BY-Klausel ein oder verwenden Sie es in einer Aggregatfunktion, damit das System weiß, wie Sie das Feld kombinieren möchten.

Angenommen, Sie haben diese Tabelle:

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

Wenn Sie GROUP BY Name sagen, woher weiß es dann, welche Bestellnummer im Ergebnis angezeigt werden soll? Sie fügen also entweder OrderNumber in group by ein, was zu diesen beiden Zeilen führt. Oder Sie verwenden eine Aggregatfunktion, um zu zeigen, wie mit den OrderNumbers umgegangen wird. Zum Beispiel, MAX(OrderNumber)was bedeutet, dass das Ergebnis ist John | 2oder SUM(OrderNumber)was bedeutet, dass das Ergebnis ist John | 3.

Tobberoth
quelle
1
Ein Hinweis: Sie können auch konstante Spalten haben, die nicht in der GROUP BY-Klausel enthalten sind. Es ist jedoch richtig, dass alle Spalten einer von drei Kategorien zugeordnet sein müssen: Eine Aggregatfunktion, eine Konstante oder sie muss in der GROUP BY-Klausel enthalten sein. Wenn ich Konstante sage, meine ich der Klarheit halber so etwas wie "Select 1 sort_order FROM table1", wobei Sie im tatsächlichen SQL einen konstanten Wert zuweisen.
ZeroK
Wie @Varun sagt, ¡beste Erklärung überhaupt! Hat mir geholfen, einfach zu verstehen, was passiert GROUP BY, ORDER BYund Funktionen zu aggregieren. Einfach, Clair, mit einem sehr einfachen Beispiel. Vielen Dank!
A. Cedano
39

Angesichts dieser Daten:

Col1  Col2  Col3
 A     X     1
 A     Y     2
 A     Y     3
 B     X     0
 B     Y     3
 B     Z     1

Diese Abfrage:

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

Würde zu genau der gleichen Tabelle führen.

Diese Abfrage:

SELECT Col1, Col2 FROM data GROUP BY Col1, Col2

Würde ergeben zu:

Col1  Col2
 A     X  
 A     Y  
 B     X  
 B     Y  
 B     Z  

Nun eine Abfrage:

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

Würde ein Problem verursachen: Die Zeile mit A, Y ist das Ergebnis der Gruppierung der beiden Zeilen

 A     Y     2
 A     Y     3

Welcher Wert sollte also in Spalte 3, '2' oder '3' stehen?

Normalerweise würden Sie a verwenden GROUP BY, um z. B. eine Summe zu berechnen:

SELECT Col1, Col2, SUM(Col3) FROM data GROUP BY Col1, Col2

In der Zeile hatten wir also ein Problem damit, dass wir jetzt (2 + 3) = 5 erhalten.

Die Gruppierung nach all Ihren Spalten in Ihrer Auswahl entspricht praktisch der Verwendung von DISTINCT. In diesem Fall ist es vorzuziehen, die Lesbarkeit des Schlüsselworts DISTINCT zu verwenden.

Also statt

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

verwenden

SELECT DISTINCT Col1, Col2, Col3 FROM data
oerkelens
quelle
was würde dazu führen SELECT Col1, Col2, Col3 FROM data GROUP BY Col1?
Santanu Sur
@SantanuSur Das schafft einfach das gleiche Problem, das ich erklärt habe, SELECT Col1, Col2, Col3 FROM data GROUP BY Col1, Col2aber mit einer zusätzlichen problematischen Spalte. Welche Werte würden Sie für Col2und Col3für die Zeile mit Col1= A erwarten ?
Oerkelens
Ich möchte nur in group the dataBezug auf eine Spalte
Santanu Sur
Angenommen, ich habe eine Tabelle mit 3 Spalten ... und die dritte Spalte enthält eine Reihe von Duplikaten. A B A BIch möchte diese Tabelle extrahieren ... ohne dass die dritte Spalte durcheinander gerät ... zum Beispiel die dritte Spalte: - Ich möchte A A B B
Holen Sie
Wird select * from table group by 3rd Columnfunktionieren?
Santanu Sur
22

Sie haben eine strikte Anforderung der GROUP BY-Klausel. Für jede Spalte, die nicht in der group-by-Klausel enthalten ist, muss eine Funktion angewendet werden, mit der alle Datensätze für die übereinstimmende "Gruppe" auf einen einzelnen Datensatz (Summe, Maximum, Min usw.) reduziert werden.

Wenn Sie alle abgefragten (ausgewählten) Spalten in der GROUP BY-Klausel auflisten, fordern Sie im Wesentlichen, dass doppelte Datensätze aus der Ergebnismenge ausgeschlossen werden. Dies ergibt den gleichen Effekt wie SELECT DISTINCT, bei dem auch doppelte Zeilen aus der Ergebnismenge entfernt werden.

Mister_Tom
quelle
7

Der einzige reale Anwendungsfall für GROUP BY ohne Aggregation besteht darin, dass Sie GROUP BY mehr Spalten als ausgewählt haben. In diesem Fall werden die ausgewählten Spalten möglicherweise wiederholt. Andernfalls können Sie auch ein DISTINCT verwenden.

Es ist erwähnenswert, dass andere RDBMS nicht erfordern, dass alle nicht aggregierten Spalten in GROUP BY enthalten sind. Wenn beispielsweise in PostgreSQL die Primärschlüsselspalten einer Tabelle in GROUP BY enthalten sind, müssen andere Spalten dieser Tabelle nicht so sein, wie sie garantiert für jede einzelne Primärschlüsselspalte unterschiedlich sind. Ich habe mir in der Vergangenheit gewünscht, dass Oracle das Gleiche tut, wie es in vielen Fällen zu kompakterem SQL geführt hätte.

David Aldridge
quelle
5

Lassen Sie mich einige Beispiele nennen.

Betrachten Sie diese Daten.

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;

Was ist jetzt in der Tabelle

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.

--aggregieren mit Gruppe von

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

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

3 rows selected.

--aggregieren Sie mit der Gruppierung nach mehreren Spalten, wählen Sie jedoch eine Teilspalte aus

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

VAL1  
---- 
b             
c             
a             
a             

4 rows selected.

- Keine Aggregation mit Gruppierung nach mehreren Spalten

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.

- Keine Aggregation mit Gruppierung nach mehreren Spalten

SELECT
      VAL1
FROM
      DATASET A
GROUP BY
      VAL1,
      VAL2;

    VAL1  
    ---- 
    b
    c
    a
    a

    4 rows selected.

Sie haben N Spalten in select (ohne Aggregationen), dann sollten Sie N oder N + x Spalten haben

SriniV
quelle
4

Verwenden Sie eine Unterabfrage, z.

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

ODER

SELECT DISTINCT field1,field2,(SELECT distinct field3 FROM tbl2 WHERE criteria) AS field3
FROM tbl1
Munawar Shah Afridi
quelle
3

Wenn Sie eine Spalte in der SELECT-Klausel haben, wie wird sie ausgewählt, wenn mehrere Zeilen vorhanden sind? Also ja, jede Spalte in der SELECT-Klausel sollte sich auch in der GROUP BY-Klausel befinden. Sie können Aggregatfunktionen in SELECT verwenden ...

Sie können eine Spalte in der GROUP BY-Klausel haben, die nicht in der SELECT-Klausel enthalten ist, aber nicht anders

Oger
quelle
2

Als Ergänzung

Grundsätzlich muss die Anzahl der Spalten gleich der Anzahl der Spalten in der GROUP BY-Klausel sein

ist keine korrekte Aussage.

  • Jedes Attribut, das nicht Teil der GROUP BY-Klausel ist, kann nicht zur Auswahl verwendet werden
  • Jedes Attribut, das Teil der GROUP BY-Klausel ist, kann zur Auswahl verwendet werden, ist jedoch nicht obligatorisch.
sancz
quelle
0

Ich weiß, dass Sie gesagt haben, Sie möchten die Gruppe verstehen, wenn Sie Daten wie diese haben:

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

Und Sie möchten, dass die Daten wie folgt aussehen:

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

Sie verwenden:

select * from table_name
order by col-c,colb

Weil ich denke, das ist, was Sie vorhaben.

user2839702
quelle