Schorsch: mysql: distinct gorup by Wer hat den Durchblick?

Guten Tag

Wie kann ich eine MySQL-Abfrage gestalten, damit unabhängig von Joins und Where-Bedingungen die Resultate nur einmal vorkommen?

Ich habe eine Abfrage über eine "grosse" Tabelle, an der etliche "kleine" Tabelle gejoint sind.

SELECT a.id, b.blah, c.blah, d.blah... usw.
FROM grosseTabelle AS a
LEFT JOIN kleineTabelle_1 AS b ON (Bedingung)
LEFT JOIN kleineTabelle_1 AS c ON (Bedingung)
usw.
WHERE (Bedingungen)

Ich möchte folgendes:
  Gebe mir alle Datensätze der "grossen" Tabelle,
  Jeder Datensatz darf nur einmal vorkommen.

Ich versuchte  SELECT DISTINCT(a.id)...
Aber auch da bekomme ich Datensätze mehrfach zurück.

Gruss
Schorsch

  1. Wenn du ein DISTINCT haben willst, dann gilt die Regel, daß du über alle anderen Tabellen sogenannte Gruppenkommandos laufen lässt (SUM, COUNT, MAX), ansonsten hast du immer einen verschiedenen Ergebniss-Datensatz.
    Und DISTINCT wäre in diesem Fall wahrscheinlich auchnicht die saubere Lösung, sondern ein GROUP BY:

    SELECT a.id, COUNT(b.blah), COUNT(c.blah), COUNT(d.blah)... usw.
    FROM grosseTabelle AS a
    LEFT JOIN kleineTabelle_1 AS b ON (Bedingung)
    LEFT JOIN kleineTabelle_1 AS c ON (Bedingung)
    usw.
    WHERE (Bedingungen) GROUP BY a.id

    1. Salut

      Und DISTINCT wäre in diesem Fall wahrscheinlich auchnicht die saubere Lösung, sondern ein GROUP BY:

      SELECT a.id, COUNT(b.blah), COUNT(c.blah), COUNT(d.blah)... usw.
      FROM grosseTabelle AS a
      LEFT JOIN kleineTabelle_1 AS b ON (Bedingung)
      LEFT JOIN kleineTabelle_1 AS c ON (Bedingung)
      usw.
      WHERE (Bedingungen) GROUP BY a.id

      Tatsächlich hilft mir "GROUP BY a.id".
      Warum und wie genau ist mir aber noch nicht ganz klar.
      Ebenfalls nicht ganz verstanden habe ich die COUNT's. Ich will ja nicht die Anzahl von b.blah, sondern den Inhalt von b.blah.

      Besten Dank!
      Schorsch

      1. Tatsächlich hilft mir "GROUP BY a.id".
        Warum und wie genau ist mir aber noch nicht ganz klar.

        Du willst ja den Datensatz aus der Tabelle a nur einmal.
        Was macht aber die Query, wenn du folgendes Ergebniss hast
        (nehmen wir mal an, das es eine logische Verknüpfung zwischen a.id und b.id in deiner Abfrage gibt) ?

        a.id | b.id
        -----+-----
          1  | 1
          1  | 2
          1  | 3
          1  | 4
          1  | 5
          1  | null

        Letztlich kriegst du den Datensatz von a.id sechsmal, obwohl du ihn nur einmal haben möchtest.

        In deinem Fall denke ich mal klappt das, weil du eine 1:1-Transition hast, daß heißt es kommen die Datensätze immer nur einmal vor.

  2. yo,

    Wie kann ich eine MySQL-Abfrage gestalten, damit unabhängig von Joins und Where-Bedingungen die Resultate nur einmal vorkommen?

    das mit DISTINCT war schon der richtige ansatz, nur dass das distinct immer nur dann wirksam wird (doppelte datensätze rausfiltert), wenn --> alle <-- spalten des jeweiligen datensatzes mit einem schon vorhanden übereinstimmen. ist der datensatz auch in nur einer spale mit einem anderen inhalt bedacht, dann greift distinct nicht. insofern ist es nicht möglich, distinct über nur eine ausgewählte spalte laufen zu lassen, sondern es ist alles oder nichts.

    die frage ist nun, was du als doppelte datensätze ansiehst...

    Gebe mir alle Datensätze der "grossen" Tabelle,
      Jeder Datensatz darf nur einmal vorkommen.

    dafür brauchst du keinen join über die kleinen tabellen, wenn es dir darum geht, nur jeden datensatz der grossen tabelle einmal auszugeben. nicht mal distinct ist dafür von nöten. willst du alle datensätze der grossen tabelle und zusätzlich informationen der kkleinen tabelle über joins, dann kann du nur die schon angesprochenen aggregat-funktionen mit ins boot nehmen, wie zum beispiel COUNT(). du müsstest quasi ein group by über alle spalten der grossen tabelle machen, die du ausgeben willst, plus dem COUNT(). versuchst du andere informationen der kleinen tabellen mitzunehmen, dann kann es sein, dass ein datensatz der grossen tabelle mehreren datensätze der kleinen tabelle zugeordnet wird. und für welchen der werte, soll sich die abfrage den entscheiden ?

    man könnte bei entsprechendem dbms auch ein wenig tricksen und unterabfragen mit ins spiel bringen.....

    Ilja

    Ich versuchte  SELECT DISTINCT(a.id)...
    Aber auch da bekomme ich Datensätze mehrfach zurück.

    Gruss
    Schorsch

    1. Salut

      das mit DISTINCT war schon der richtige ansatz, nur dass das distinct immer nur dann wirksam wird (doppelte datensätze rausfiltert), wenn --> alle <-- spalten des jeweiligen datensatzes mit einem schon vorhanden übereinstimmen.

      OK: DISTINCT habe ich begriffen.

      die frage ist nun, was du als doppelte datensätze ansiehst...

      In diesem Beispiel sind für mich doppelte Datensätze, wenn in einem Abfrageresultat dieselbe ID von der Spalte ID der grossen Tabelle vorkommt. Im Resultat darf nicht eine a.id doppelt vorkommen.

      Gebe mir alle Datensätze der "grossen" Tabelle,
        Jeder Datensatz darf nur einmal vorkommen.

      dafür brauchst du keinen join über die kleinen tabellen, wenn es dir darum geht, nur jeden datensatz der grossen tabelle einmal auszugeben.

      Hier meine ich mit Datensatz eine Resultatenmenge, welche aus dem Inhalt der grossen Tabelle _und_ dem Inhalt vieler kleinen Tabellen besteht. Daher habe ich zu den Joins gegriffen.

      Ich glaube mir hilft ein GROUP BY, obwohl ich noch nicht glasklar verstanden habe, was das genau macht.

      Besten Dank!
      Schorsch

      1. yo,

        In diesem Beispiel sind für mich doppelte Datensätze, wenn in einem Abfrageresultat dieselbe ID von der Spalte ID der grossen Tabelle vorkommt. Im Resultat darf nicht eine a.id doppelt vorkommen.

        ich gehe mal davon aus, dass du doppelte datensätze (id der grossen tabelle) bekommen hast, sonst würde der post ja keinen sinn machen. dass bedeutet aber auch, dass es sich bei den tabellen um kein 1:1 verhältnis handelt. oder mit anderen worten, man kann einer id der grossen tabelle mehrere datensätze der kleinen tabelle zuordenen. das gleiche wurde dir aber schon von flash gesagt.

        wenn nun aber eine id der grossen tabelle mehrere id's der kleinen tabellen zugeordnet werden kann, du aber nur eine "grosse" id haben willst, dann muss eine enscheidung her, welche der mehreren "kleinen" id's du nun haben willst, weil alle bekommst du nicht ins boot.

        Ich glaube mir hilft ein GROUP BY, obwohl ich noch nicht glasklar verstanden habe, was das genau macht.

        solange du keine aggregat-funktionen wie COUNT() verwenden willst, brauchst du den join und die kleinen tabellen nicht. man kann es zwar mit machen, ist aber unnötig und zuviel des guten.

        Ilja

        1. Salut

          ich gehe mal davon aus, dass du doppelte datensätze (id der grossen tabelle) bekommen hast, sonst würde der post ja keinen sinn machen. dass bedeutet aber auch, dass es sich bei den tabellen um kein 1:1 verhältnis handelt.

          Genau.

          wenn nun aber eine id der grossen tabelle mehrere id's der kleinen tabellen zugeordnet werden kann, du aber nur eine "grosse" id haben willst, dann muss eine enscheidung her, welche der mehreren "kleinen" id's du nun haben willst, weil alle bekommst du nicht ins boot.

          Ich habe einen LEFT JOIN, mit einer 1:N Verbindung im der MySQL-Abfrage drin. Ich muss mich aber nicht entscheiden, welche "kleinen" ID's ich von dieser Tabelle haben möchte, weil ich sie nicht brauche.

          Warum ich denn trotzdem diesen LEFT JOIN habe?
          Weil ich diese MySQL Abfrage zentral aufbewahre und an verschiednen Orten einsetze. An einem anderen Ort brauche ich dann
          "LEFT JOIN Tabelle mit 1:N id = Zahl"
          Damit ich nicht jedesmal eine neue MySQL Abfrage schreiben muss, dachte ich, ich schreibe _eine_ MySQL Abfrage, die ich überall einsetzen kann. Vielleicht ist aber gerade das der falsche Ansatz.

          Vielen Dank!
          Schorsch

          1. yo,

            Damit ich nicht jedesmal eine neue MySQL Abfrage schreiben muss, dachte ich, ich schreibe _eine_ MySQL Abfrage, die ich überall einsetzen kann. Vielleicht ist aber gerade das der falsche Ansatz.

            ich denke auch, dass man diesen anspruch von universellen abfragen lieber nicht weiterführen sollte. es macht dinge sehr kompliziert, die eigentlich sehr einfach wären. eine abfrage über die grosse tabelle, spart zeit und schont ressourcen.

            Ilja