Announcement

Collapse
No announcement yet.

Distinct Frage

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

  • Distinct Frage

    Hallo zusammen,

    ich bin noch relativ neu in Sachen Datenbank und habe folgendes Problem:

    Angenommen ich habe ein tabelle die die Spalten "nummer" und "name" hat.
    Zu einer Nummer kann es mehrere Namen geben, das sieht dann so aus:
    Code:
    nummer        name
       1          aaa
       1          bbb
       2          ccc
       2          ccc

    ich möchte jetzt eine Abfrage erstellen die jede nummer jeweil NUR EINMAL zurück gibt und den Namen. Wenn der Name bei allen nummern gleich ist soll dieser name zurückgegeben werden, wenn er verschieden ist soll ein "*" zurückgeggebn werden, sprich meine Abfrage soll mir folgendes Ergebnis liefern:
    Code:
    nummer  name
       1     *
       2     ccc
    ich habe schon mit Distinct und Group By rumgespielt, aber keine möglichkeit gesehen mein gewünschtes Ergebnis zu erreichen.
    Ich glaube auch dass das kein triviales Problem ist, hoffe aber ich liege falsch ;-)

    Vielen Dank für eure hilfe!
    OhNo

  • #2
    Der folgende Code liefert das gewünschte Ergebnis:
    Code:
    SELECT nummer, (SELECT DISTINCT name FROM t_ccc ii WHERE ii.nummer = a.nummer) AS name
       FROM t_ccc a
       GROUP by nummer
       HAVING 1 = (SELECT COUNT(DISTINCT name)
                     FROM t_ccc i
                    WHERE i.nummer = a.nummer)
    UNION
    SELECT nummer, '*' AS name
       FROM t_ccc a
       GROUP by nummer
       HAVING 1 < (SELECT COUNT(DISTINCT name)
                     FROM t_ccc i
                    WHERE i.nummer = a.nummer)
    ;
    Ausgabe
    Code:
        NUMMER NAME
    ---------- ----------
             1 *
             2 ccc
    kuemmelchen

    Comment


    • #3
      Man könnte auch den CASE-Operator verwenden:
      Code:
      WITH data AS
      (
      SELECT 1 nummer, 'aaa' name FROM dual
        UNION ALL
      SELECT 1       , 'bbb'      FROM dual
        UNION ALL
      SELECT 2       , 'ccc'      FROM dual
        UNION ALL
      SELECT 2       , 'ccc'      FROM dual
      )
      SELECT 
        CASE 
          WHEN count(distinct name)= 1 THEN min(name) 
      	ELSE '*'
      	END  col, nummer
      FROM data
      GROUP BY nummer
      ORDER BY nummer
      Das gibt ebenfalls das gewünschte Ergebnis:
      Code:
      COL	NUMMER
      
      *	1
      ccc	2

      Comment


      • #4
        Hey,

        Danke erstmal an eure Vorschläge, funktionieren tun sie super, allerdings hab ich das Problem dass ich noch ca 4 andere Spalten habe bei denen auch ein "*" dargestellt werden soll, im Falle von unterschiedlichen Werten
        Und wenn ich das richtig überblicke wird meine SQL Abfrage dann sooooooooo kompliziert und groß, dass ich es gleich in java machen kann.

        Oder liege ich da falsch bzw. gibt es eine andere Lösung?
        Grüße
        Ohnoooo

        Comment


        • #5
          Gib doch mal ein Beispiel, ggf. basierend auf der
          WITH data AS
          Query oder als Tabellendefinition mit dem erwarteten Ergebnis. Die Abfrage wird vermutlich nicht soooooooooo kompliziert, aber ich kann nur raten, ob z.B. ALLE Spalten unterschiedliche Werte haben müssen oder nur eine...
          Zuletzt editiert von jum; 16.07.2009, 12:45.

          Comment


          • #6
            Hi Jum,

            ich hab das Beispiel mit dem
            WITH data AS ehrlich gesagt nicht ganz verstanden. Ich hab überhaupt keine Ahnung was das eigentlich macht. Falls du mir ne kurze Erklärung geben könntest wär das sehr nice.

            Wenn ich das Select case Statement alleine benutze funktioniert es ganz gut,
            und ich kann ja mit dem fast identischen Case Statement noch andere spalten abfragen.

            Allerdings hab ich noch ein anderes Problem: Wie baue ich jetzt noch ein Where clausel ein, die ein anderes Feld abfragt? Beispiel:
            Meine Tabelle sieht so aus: (DAS FELD "kundenid" IST PRO NUMMER IMMER GLEICH)

            Code:
            nummer  name  nachname   kundenid
            --------------------------------------------
            1        aaa      111        4
            1        aaa      222        4
            2        eee      333        5
            2        eeg      333        5
            Als Resultat meiner Abfrage will ich jetzt nur die mit der kundenid 4. Wenn alle namen gleich sind dann soll der name erscheinen, wenn er unterschiedlich ist soll ein stern erscheinen, in dem fall sieht das result so aus:

            Code:
            nummer name nachname kundenid
            --------------------------------------------
            1     aaa     *     4
            Mein versuch sah so aus:

            Code:
            SELECT 
              CASE 
                WHEN count(distinct name)= 1 THEN min(name) 
            	ELSE '*'
            	END  name, 
             CASE 
                WHEN count(distinct nachname)= 1 THEN min(nachname) 
            	ELSE '*'
            	END  nachname, nummer
            FROM data where kundenid = 4
            GROUP BY nummer
            ORDER BY nummer
            Das funktioniert leider nicht, wobei ich denke dass das nicht so schwer ist, nur ich wie gesagt in SQL nicht so fit bin (ich arbeite dran ;-).

            Danke + Grüße
            OhNo

            Comment


            • #7
              Hallo,

              das kommt mir alles ein wenig komliziert vor. Nachfolgend mein Vorschlag...

              Code:
              SELECT
              tux.nummer, tux.kundenid, IF(COUNT(tux.nummer) > 1, tux.name, '*') AS name, IF(COUNT(tux.nummer) > 1, tux.nachname, '*') AS nachname
              FROM
              tux
              WHERE
              tux.kundenid = 4
              GROUP BY
              tux.name, tux.nachname
              Besten Gruß

              Comment


              • #8
                Hey,

                danke für deine Lösung, sieht ziemlich gleich aus nur dass du Ifs anstatt CASE benutzt, was aber bei deiner Abfrage das Problem ist dass du nach name und nachname gruppierst, es soll aber ein group by nummer sein.

                Gruß
                OhNo

                Comment


                • #9
                  Hm, verstehe ich zwar nicht ganz. Ich will ja wissen ob der name, oder nachname mehr als einmal vorkommt. Daher das Group BY name, nachname. Man könnte SELECT DISTINCT...
                  schreiben, damit man die '*' Datensätze nicht mehrfach bekommt.

                  Besten Gruß
                  Zuletzt editiert von connection_reset; 17.07.2009, 11:28.

                  Comment


                  • #10
                    Nein das hast du falsch verstanden. Du kannst dir das so vorstellen:
                    Die Nummer könnte eine GruppenId sein. Dieser Gruppe sind verschiedene Leute zugeordnet. Jetzt will ich alle Gruppen auflisten die es gibt, wenn in der Gruppe alle Leute denselben Vornamen haben soll dieser angezeigt werden ansonsten ein "*". Wenn du dir die Beispiele oben anschaust wird dort auch bereits der DISTINCT verwendet


                    Natürlich könnte man hier zwei Tabellen machen aber das kommt aus speziellen Gründen für uns nicht in Frage.

                    Gruß
                    OhNo

                    Comment


                    • #11
                      @connection_reset

                      Deine Gruppierung ist syntaktisch falsch.

                      In der SELECT-Klausel können nur Spalten angegeben werden, die auch in der GROUP BY-Klausel vorkommen oder die zusammen mit einer Gruppenfunktion verwendet werden.

                      Da du über name und nachname gruppierst, dürfen beide Spalten in der SELECT-Klausel verwendet werden.
                      COUNT(tux.nummer) ist erlaubt, da COUNT eine Gruppenfunktion ist.
                      tux.kundenid und tux.nummer dürfen in der SELECT-Klausel nicht verwendet werden, da in der GROUP BY-Klausel nicht enthalten bzw. nicht zusammen mit einer Gruppenfunktion verwendet.

                      Leider ist die Lösung nicht so einfach, wie du dir das so vorstellst.

                      kuemmelchen

                      Comment


                      • #12
                        @kuemmelchen

                        Stimmt, Du hast recht. Ich hab das Bespiel auf die Schnelle nur in MySQL getestet und da wird etwas schlamiper mit der Syntax umgegangen. Abgesehen davon könnte ich mit meiner Abfrage nicht innerhalb einer Gruppe den Vornamen anuzeigen und den Nachnamen als * ausgeben. Bei mir gibt es nur '*' wenn ein Feld abweicht.

                        Grüße

                        Comment


                        • #13
                          Also ich poste jetzt nochmal mein Problem, da das in der anderen Debatte inzwischen untergegangen ist:

                          ich hab das Beispiel mit dem
                          WITH data AS ehrlich gesagt nicht ganz verstanden. Ich hab überhaupt keine Ahnung was das eigentlich macht. Falls du mir ne kurze Erklärung geben könntest wär das sehr nice.

                          Wenn ich das Select case Statement alleine benutze funktioniert es ganz gut,
                          und ich kann ja mit dem fast identischen Case Statement noch andere spalten abfragen.

                          Allerdings hab ich noch ein anderes Problem: Wie baue ich jetzt noch ein Where clausel ein, die ein anderes Feld abfragt? Beispiel:
                          Meine Tabelle sieht so aus: (DAS FELD "kundenid" IST PRO NUMMER IMMER GLEICH)


                          Code:
                          nummer  name  nachname   kundenid
                          --------------------------------------------
                          1        aaa      111        4
                          1        aaa      222        4
                          2        eee      333        5
                          2        eeg      333        5
                          Als Resultat meiner Abfrage will ich jetzt nur die mit der kundenid 4. Wenn alle namen gleich sind dann soll der name erscheinen, wenn er unterschiedlich ist soll ein stern erscheinen, in dem fall sieht das result so aus:


                          Code:
                          nummer name nachname kundenid
                          --------------------------------------------
                          1     aaa     *     4
                          Mein versuch sah so aus:



                          Code:
                          SELECT 
                            CASE 
                              WHEN count(distinct name)= 1 THEN min(name) 
                          	ELSE '*'
                          	END  name, 
                           CASE 
                              WHEN count(distinct nachname)= 1 THEN min(nachname) 
                          	ELSE '*'
                          	END  nachname, nummer
                          FROM data where kundenid = 4
                          GROUP BY nummer
                          ORDER BY nummer
                          Das funktioniert leider nicht, wobei ich denke dass das nicht so schwer ist, nur ich wie gesagt in SQL nicht so fit bin (ich arbeite dran ;-).

                          Danke + Grüße
                          OhNo

                          Comment


                          • #14
                            WITH data AS ehrlich gesagt nicht ganz verstanden.
                            Mit Hilfe der WITH-Klausel können gelesene Daten temporär zwischengespeichert werden. Sowohl in der eigentlichen SELECT-Anweisung als auch in anderen Teilen von WITH kann auf die gespeicherte Ergebnismenge zugegriffen werden, ohne sie neu berechnen zu lassen.

                            Beispiel von jum
                            WITH data AS
                            (
                            SELECT 1 nummer, 'aaa' name FROM dual
                            UNION ALL
                            SELECT 1 , 'bbb' FROM dual
                            UNION ALL
                            SELECT 2 , 'ccc' FROM dual
                            UNION ALL
                            SELECT 2 , 'ccc' FROM dual
                            )
                            SELECT
                            CASE
                            WHEN count(distinct name)= 1 THEN min(name)
                            ELSE '*'
                            END col, nummer
                            FROM data
                            GROUP BY nummer
                            ORDER BY nummer
                            Die gelesene Datensatzmenge aus
                            SELECT 1 nummer, 'aaa' name FROM dual
                            UNION ALL
                            SELECT 1 , 'bbb' FROM dual
                            UNION ALL
                            SELECT 2 , 'ccc' FROM dual
                            UNION ALL
                            SELECT 2 , 'ccc' FROM dual
                            wird unter dem Namen data temporär gespeichert. Auf diese temporäre Datensatzmenge wird in der eigentlichen SELECT-Anweisung zugegriffen: FROM data.

                            kuemmelchen

                            Comment


                            • #15
                              Code:
                              DROP TABLE t_ccc;
                              
                              CREATE TABLE t_ccc
                              (
                                nummer   number,
                                name     varchar2(10),
                                nachname varchar2(10),
                                kundenid number
                              );
                              
                              
                              INSERT INTO t_ccc
                                VALUES(1, 'aaa', '111', 11);
                              
                              INSERT INTO t_ccc
                                VALUES(1, 'aaa', '111', 11);
                              
                              INSERT INTO t_ccc
                                VALUES(2, 'bbb', '222', 12);
                              
                              INSERT INTO t_ccc
                                VALUES(2, 'bbb', '333', 12);
                              
                              INSERT INTO t_ccc
                                VALUES(3, 'ccc', '444', 13);
                              
                              INSERT INTO t_ccc
                                VALUES(3, 'ddd', '444', 13);
                              
                              INSERT INTO t_ccc
                                VALUES(4, 'eee', '555', 14);
                              
                              INSERT INTO t_ccc
                                VALUES(4, 'fff', '666', 14);
                              
                              SELECT * FROM t_ccc;
                              
                              
                              WITH
                                g1 AS
                                  (SELECT nummer,
                                          (SELECT DISTINCT name FROM t_ccc ii WHERE ii.nummer = a.nummer) AS name,
                                          (SELECT DISTINCT kundenid FROM t_ccc ii WHERE ii.nummer = a.nummer) kundenid
                                     FROM t_ccc a
                                     GROUP by nummer
                                     HAVING 1 = (SELECT COUNT(DISTINCT name)
                                                   FROM t_ccc i
                                                  WHERE i.nummer = a.nummer)
                                     UNION
                                   SELECT nummer, '*' AS name,
                                          (SELECT DISTINCT kundenid FROM t_ccc ii WHERE ii.nummer = a.nummer)
                                     FROM t_ccc a
                                     GROUP by nummer
                                     HAVING 1 < (SELECT COUNT(DISTINCT name)
                                                   FROM t_ccc i
                                                  WHERE i.nummer = a.nummer)
                                  ),
                                 g2 AS
                                    (SELECT nummer, MIN(nachname) as nachname
                                       FROM (SELECT nummer, name,
                                              (SELECT DISTINCT nachname FROM t_ccc ii WHERE ii.nummer = a.nummer)         
                              
                                           nachname,
                                              (SELECT DISTINCT kundenid FROM t_ccc ii WHERE ii.nummer = a.nummer)         
                              
                                           kundenid
                                                  FROM t_ccc a
                                                  GROUP by nummer, name
                                                  HAVING 1 = (SELECT COUNT(DISTINCT nachname)
                                                                FROM t_ccc i
                                                               WHERE i.nummer = a.nummer)
                                                UNION
                                                SELECT nummer, name, '*' AS name,
                                                  (SELECT DISTINCT kundenid FROM t_ccc ii WHERE ii.nummer = a.nummer)
                                                    FROM t_ccc a
                                                   GROUP by nummer, name
                                                   HAVING 1 < (SELECT COUNT(DISTINCT nachname)
                                                                 FROM t_ccc i
                                                                WHERE i.nummer = a.nummer
                                               )
                                             )
                                       GROUP BY nummer
                                     )
                              SELECT g1.nummer,g1.name, g2.nachname, g1.kundenid
                                FROM g1,g2
                                WHERE g1.nummer = g2.nummer;
                              liefert als Ergebnis
                              Code:
                                  NUMMER NAME       NACHNAME     KUNDENID
                              ---------- ---------- ---------- ----------
                                       1 aaa        111                11
                                       2 bbb        *                  12
                                       3 *          444                13
                                       4 *          *                  14
                              kuemmelchen

                              Comment

                              Working...
                              X