Announcement

Collapse
No announcement yet.

Distinct und Group By

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Distinct und Group By

    Hi,
    ich lerne gerade SQL und bin auf GROUP BY und DISTINCT gestoßen. Mir erschließt sich nicht wirklich weshalb ich DISTINCT überhaupt verwenden sollte.

    Nach meiner jetzigen Sicht schließt distinct doppelte Daten aus. Allerdings sind die selben Ergebnisse auch mit GROUP BY möglich. Das macht im speziellen keinen Unterschied wenn ich von einer anderen Programmiersprache auf die Ergebnismenge zugreife.

    Was mir noch mehr zu schaffen macht, in einem einfachen Test, mit dieser Tabelle:

    Code:
    Warengruppe, Name, Ist
    essen, Kekse , 3
    essen, SCHOKOLADE, 2
    essen, MarZipAn, 1
    trinken, coca-cola, 0
    trinken, FANTa, 8
    besteck, teLLer, 2
    besteck, gabeln, 1
    auf welche ich folgende Abfragen aufwende:
    SELECT `Warengruppe`FROM `test`GROUP BY Warengruppe

    SELECT DISTINCT `Warengruppe`FROM `test`
    ist GROUP BY mit 0.0007 sek. schneller als DISTINCT mit 0.0008 sek.


    In vielen Forenbeiträgen die ich über die Vergleiche gelesen habe wurde zwar gesagt, das es sich bei beiden Abfragen um grundlegend andere Dinge handelt. Aber wenn sich die selbe Ergebnismenge auch über ein GROUP BY erreichen lässt, der Befehl "Mächtiger" als der andere und gleichzeitig schneller ist, frag ich mich weshalb ich DISTINCT überhaupt verwenden sollte.

    Etliche male wurde darauf hingewiesen das DISTINCT eben für viele überschaubarer wäre. Das halte ich allerdings für totalen Quatsch. Es kann doch nicht die Intention der SQL-Entwickler gewesen sein, einfach nur einen Befehl einzuführen, nur weil der Code dann für manche leichter lesbar wäre. Ein Befehl wäre meiner Meinung nach auch lesbarer.

    Ich schätze das es ein Anwendungsgebiet für DISTINCT gibt das sich mir noch nicht erschlossen hat. Irgendeine Daseinsberechtigung muss es ja haben..

  • #2
    DISTINCT dampft doppelte Datensätze einfach nur ein.
    GROUP BY gruppiert, wenn Du in Deinem SQL Aggregatsfunktionen verwendest.

    Code:
    select max(col1),col2 from tabelle group by col2
    Das GROUP BY ist hierbei eine Pflichtangabe, auch wenn mysql in älteren Versionen das nicht anmeckert aber dafür auch z.T. seltsame ergebnisse liefert.

    Verwendest Du keine Aggregatsfuktionen und möchtest einfach nur eindampfen, dann schreibt man DISTINCT. Statt dessen ein GROUP BY zu verwenden ist möglich aber schlechter Stil.

    ist GROUP BY mit 0.0007 sek. schneller als DISTINCT mit 0.0008 sek.
    Das ist nicht wirklich eine seriöse Messung. Welchen Anteil davon hat die Platte, das Netzwerk, hat der Virenscanner vielleicht grade was gemacht etc.

    SELECT `Warengruppe`FROM `test`GROUP BY Warengruppe
    Die Backticks ` brauchst Du nicht und sind eine der vielen Krankheiten, die sich mysql Benutzer im laufe der Zeit angewöhnen und weitergeben.

    Ich würde dir empfehlen SQL mit postgres, mssql, oracle etc. zu lernen aber nicht unbedingt mysql.

    Dim
    Zitat Tom Kyte:
    I have a simple philosophy when it comes to the Oracle Database: you can treat it as a black box and just stick data into it, or you can understand how it works and exploit it as a powerful computing environment.

    Comment


    • #3
      Hi,

      ein Vorteil von distinct ist, dass man nicht jede Spalte zweimal hinschreiben muss, was bei vielen Spalten schon lästig sein kann. Ausserdem kannst Du, wenn Du die komplette Tabelle betrachten willst einfach schreiben:

      select distinct * from test

      Gruß
      docendo discimus

      Comment


      • #4
        @distinct:
        Die Funktionsweise ist mir schon bekannt. Wie gesagt, kann ich aber mit beiden das selbe Ergebnis erreichen -> wodurch ich zB. in Php die selbe Ergebnismenge erreiche.

        MySQL läuft hier auf nem Windows XP-Rechner mit 2Ghz, 1Gbyte Ram, wurde mit XAMPP installiert. Virenscanner ist nicht installiert. Es laufen 38 Prozesse, meine Entwicklungsanwendungen eingeschlossen. Aber auch wenn ich aufs Minimum der Prozesse herunterdrossel, also alles ausschalte, ist das Ergebnis das selbe. Die Backticks `werden von phpmyadmin automatisch eingefügt.. :\

        Oracle und SQL92 wird mit behandelt, also auf Unterschiede hingewiesen. Ich muss mal fragen ob ich evtl. Zugriff auf ne Oracle-Datenbank zum testen bekomm. Unter MySql ist es hier tatsächlich so, das die Abfragen in unterschiedlichen Tabellen für GROUP BY immer ein schnelleres Ergebnis liefert.

        Hast du vielleicht mal exemplarisch ein Anwendungsbeispiel in nem realitätsnahen Scenario? Wann würde man DISTINCT und wann GROUP BY einsetzen? Ich schätze, dass das erst bei komplexeren Abfragen einen Unterschied macht, kann mir aber nicht richtig vorstellen in welchem Zusammenhang..


        @frauwue:
        Naja.. fraglich ob das wirklich der Grund war weshalb der Befehl eingeführt wurde. Ist aber n netter Hinweis für Tabellen mit vielen Spalten (wobei ich mir dann wiederum Gedanken über mein ER-Modell machen würde)
        Zuletzt editiert von sfxOn; 16.07.2010, 11:09.

        Comment


        • #5
          Hast du vielleicht mal exemplarisch ein Anwendungsbeispiel in nem realitätsnahen Scenario? Wann würde man DISTINCT und wann GROUP BY einsetzen? Ich schätze, dass das erst bei komplexeren Abfragen einen Unterschied macht, kann mir aber nicht richtig vorstellen in welchem Zusammenhang..
          Eine Tabelle mit Umsatzzahlen pro Tag für ein ganzes Geschäftsjahr (also ca. 220 Datensätze). Errechne die Summe der Umsätze pro Monat. In Oracle würde man das so machen:
          Code:
          SELECT SUM(UMSATZ_PRO_TAG) MONATSUMSATZ,
                 TO_CHAR(UMSATZ_DATUM,'MM.YYYY') MONAT 
            FROM UMSATZTABELLE
          GROUP BY TO_CHAR(UMSATZ_DATUM,'MM.YYYY')
          Das Ergebnis würde dann etwa so aussehen:
          Code:
          1234,45  01.2010
          34567,56 02.2010
          3456,33  03.2010
          ...
          88694,75 12.2010
          Mach das mal mit DISTINCT

          Oracle und SQL92 wird mit behandelt, also auf Unterschiede hingewiesen. Ich muss mal fragen ob ich evtl. Zugriff auf ne Oracle-Datenbank zum testen bekomm.
          Runterladen und installieren.

          Dim
          Zitat Tom Kyte:
          I have a simple philosophy when it comes to the Oracle Database: you can treat it as a black box and just stick data into it, or you can understand how it works and exploit it as a powerful computing environment.

          Comment


          • #6
            Ok, du hast mich n bisschen zu wörtlich genommen. Ich hätte das ganze noch auf die Tatsache einschränken sollen, das das Ergebnis sowohl mit Distinct als auch Group By erreichbar ist.

            Meine Überlegung:
            Es muss doch einen wirklich driftigen Grund geben, DISTINCT zu verwenden. Irgendein Ergebnis das mit GROUP BY nicht erreichbar ist. Darauf will ich hinaus.

            Edit:
            Vielleicht gibt es auch ein Anwendungsgebiet in dem beide Befehle gleichzeitig verwendet werden. Ich kann mir da aber gerade nichts vorstellen. Scheint komplexer zu werden..
            Zuletzt editiert von sfxOn; 16.07.2010, 11:51.

            Comment


            • #7
              Es muss doch einen wirklich driftigen Grund geben, DISTINCT zu verwenden.
              Ja, wenn man einfach nur doppelte Sätze eindampfen will.

              Irgendein Ergebnis das mit GROUP BY nicht erreichbar ist.
              Ja:
              Code:
              SELECT DISTINCT * FROM TABELLE
              Anstelle von
              Code:
              SELECT col1,col2,col3,col4,col5,col6,col7,col8,col9 FROM TABELLE
              GROUP BY col1,col2,col3,col4,col5,col6,col7,col8,col9
              So kurz und prägnant kannst Du nur mit DISTINCT eindampfen.

              Damit will ich es von meiner Seite aus auch bewenden lassen.

              Dim
              Zitat Tom Kyte:
              I have a simple philosophy when it comes to the Oracle Database: you can treat it as a black box and just stick data into it, or you can understand how it works and exploit it as a powerful computing environment.

              Comment


              • #8
                Das Beispiel ist nicht schlecht.. Noch nicht ganz 100% überzeugend, aber trotzdem gut. Ein ungutes Gefühl, nicht wirklich zu wissen was dahinter steckt bleibt allerdings.

                Kommt man denn irgendwie an den Quelltext? Das würde mir vielleicht ein bisschen genauer erklären was da passiert. An wen könnt ich mich denn sonst noch wenden?

                Comment


                • #9
                  Ich habe gerade das fehlende Puzzlestück gefunden. Mit Hilfe von DISTINCT lassen sich unter GROUP BY die Ergebnissmengen noch passgerechter Zusammenfassen, also doch andere Ergebnismengen erzielen.

                  Ich übernehme mal die Daten aus der Lektion:

                  Code:
                  ID, Kunde, Beschreibung, Betrag
                  1, Betz, Ersatzgebühr, 40
                  2, Betz, Mitgliederbeitrag, 50
                  3, Polak, Mitgliederbeitrag, 50
                  4, Betz, Mahngebühr, NULL
                  5, Kampinski, Kaution, NULL
                  6, Mayer, Ersatzgebühr, 40
                  7, Polak, Mahngebühr, 80
                  8, Polak, Ersatzgebühr, 40
                  9, Betz, NULL, 35
                  10, Mayer, Ersatzgebühr, 45
                  11, Mayer, NULL, 45
                  Wenn man diese Datenmenge jetzt zB. folgendermaßen Abfragt:

                  Code:
                  SELECT COUNT(Beschreibung), Kunde
                  FROM Kasseneinnahmen
                  GROUP BY Kunde;
                  interpretiert MySQL die Stelle
                  Code:
                  COUNT(Beschreibung)
                  durch die Voreinstellung automatisch als:
                  Code:
                  COUNT(ALL Beschreibung)
                  und man erhält eine Ergebnismenge in der Form:

                  Code:
                  COUNT(ALL Beschreibung), Kunde
                  3,  Betz
                  3,  Polak
                  1,  Kampinski
                  2,  Mayer
                  Wenn man jetzt statt all, Distinct anwendet, werden doppelte Einträge entfernt (COUNT(DISTINCT Beschreibung)) und man erhält ein Ergebnis bei dem doppelte Beschreibungen nicht mit aufgeführt werden:

                  Code:
                  COUNT(DISTINCT Beschreibung), Kunde
                  3, Betz
                  3, Polak
                  1, Kampinski
                  1, Mayer
                  Das ganze macht also erst bei Verwendung mit Aggregatfunktionen wirklich Sinn. Ich war wohl etwas zu ungeduldig.
                  Ich schätze das es noch weitere Anwendungsmöglichkeiten gibt, wenn ich weiter in die Materie eintauche..

                  Comment


                  • #10
                    Hallo sfxOn,

                    es wurde zwar schon viel geschrieben und ist auch schon ein paar Tage her, aber ich möchte auch noch meinen Senf dazu geben .
                    Vlt. macht die Verwendung von DISTINCT noch etwas mehr Sinn, wenn du dir die exakte Definition des SELECT-Befehls ansiehst. Der lautet nämlich:
                    SELECT [ ALL | DISTINCT ]...
                    Bei jedem Select ist also anzugeben, ob die Ergebnismenge alle oder nur eindeutige Zeilen enthalten soll. Die Angabe von ALL kann jedoch weggelassen werden und ist die Voreinstellung. Man sieht also auf einen Blick, welche Art von Ergebnis man erwarten kann, ohne erst das komplette Statement analysieren zu müssen. Bei Ein- und Zweizeilern mag das irrelavant sein, aber es gibt durchaus komplexere Statements .

                    Das DISTINCT doppelte Datensätze einfach ignoriert, indem sie aus der Ergebnismenge entfernt - oder "eingedampft" - werden, hat dim ja schon geschrieben. Hier liegt dann auch der Unterschied zum GROUP BY. Beim GROUP BY werden Datensätze also nicht einfach ignoriert, sondern gruppiert und dabei impliziert sortiert!

                    Beispiel:
                    [highlight=sql]
                    CREATE TABLE distincttest (
                    id int(8) NOT NULL AUTO_INCREMENT,
                    name varchar(64) NOT NULL,
                    PRIMARY KEY (`id`)
                    );
                    INSERT INTO distincttest (name) VALUES
                    ('Otto'),
                    ('Kurt'),
                    ('Karl'),
                    ('Otto'),
                    ('Kurt'),
                    ('Max'),
                    ('Otto'),
                    ('Max');
                    [/highlight]

                    Die Abfrage mit DISTINCT:
                    [highlight=sql]
                    select distinct name
                    from distincttest
                    [/highlight]
                    Otto
                    Kurt
                    Karl
                    Max

                    Und mit GROUP BY:
                    [highlight=sql]
                    select name
                    from distincttest
                    group by name
                    [/highlight]
                    Karl
                    Kurt
                    Max
                    Otto

                    Beide Ergebnismengen enthalten zwar die gleichen Werte und besitzen diesselbe Anzahl an Datensätzen, aber sie sind NICHT IDENTISCH!

                    Zu deiner Performancemessung: Die ist mit den wenigen Datensätzen sicherlich einfach unseriös und genügt keiner statistischen Sicherheit. In der Praxis, mit entsprechend vielen Datensätzen und höherer Komplexität wird ein GROUP BY immer langsamer sein als ein einfaches DISTINCT.

                    Gruß Falk
                    Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

                    Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

                    Comment

                    Working...
                    X