webentwicklung-frage-antwort-db.com.de

GROUP BY - Gruppiert NULL nicht

Ich versuche, mithilfe der Funktion group by eine Methode zu finden, mit der Ergebnisse zurückgegeben werden können.

GROUP BY funktioniert wie erwartet, aber meine Frage lautet: Ist es möglich, das NULL-Feld von group by ignore zu ignorieren? Damit es keine NULL-Werte gruppiert, brauche ich immer noch alle Zeilen, in denen das angegebene Feld NULL ist.

SELECT `table1`.*, 
    GROUP_CONCAT(id SEPARATOR ',') AS `children_ids`
FROM `table1` 
WHERE (enabled = 1) 
GROUP BY `ancestor` 

Nehmen wir also an, ich habe 5 Zeilen und das Vorfahrenfeld ist NULL. Es gibt 1 Zeile zurück. Aber ich möchte alle 5 Zeilen.

59
slik

Vielleicht sollten Sie den Nullspalten etwas hinzufügen, um sie eindeutig zu machen und sie danach zu gruppieren? Ich habe nach einer Sequenz gesucht, die anstelle von UUID () verwendet werden kann, aber dies könnte genauso gut funktionieren.

SELECT `table1`.*, 
    IFNULL(ancestor,UUID()) as unq_ancestor
    GROUP_CONCAT(id SEPARATOR ',') AS `children_ids`
FROM `table1` 
WHERE (enabled = 1) 
GROUP BY unq_ancestor
58
bot403

Bei der Gruppierung nach Spalte Y werden alle Zeilen, für die der Wert in YNULL ist, zusammen gruppiert.

Dieses Verhalten ist durch den SQL-2003-Standard definiert , obwohl es etwas überraschend ist, weil NULL nicht gleich NULL ist.

Sie können dies umgehen, indem Sie einen anderen Wert gruppieren, einige Funktion (mathematisch gesehen) der Daten in Ihrer Gruppierungsspalte.

Wenn Sie eine eindeutige Spalte X haben, ist dies einfach.


Eingang

X      Y
-------------
1      a
2      a
3      b
4      b
5      c
6      (NULL)
7      (NULL)
8      d

Ohne zu reparieren

SELECT GROUP_CONCAT(`X`)
  FROM `tbl`
 GROUP BY `Y`;

Ergebnis:

GROUP_CONCAT(`foo`)
-------------------
6,7
1,2
3,4
5
8

Mit Verlegenheit

SELECT GROUP_CONCAT(`X`)
  FROM `tbl`
 GROUP BY IFNULL(`Y`, `X`);

Ergebnis:

GROUP_CONCAT(`foo`)
-------------------
6
7
1,2
3,4
5
8

Schauen wir uns einmal genauer an, wie das funktioniert

SELECT GROUP_CONCAT(`X`), IFNULL(`Y`, `X`) AS `grp`
  FROM `tbl`
 GROUP BY `grp`;

Ergebnis:

GROUP_CONCAT(`foo`)     `grp`
-----------------------------
6                       6
7                       7
1,2                     a
3,4                     b
5                       c
8                       d

Wenn Sie keine eindeutige Spalte haben, die Sie verwenden können, können Sie versuchen, stattdessen einen eindeutigen Platzhalterwert zu generieren. Ich überlasse dies dem Leser als Übung.

GROUP BY IFNULL(required_field, id)

21
Hett
SELECT table1.*, 
    GROUP_CONCAT(id SEPARATOR ',') AS children_ids
FROM table1
WHERE (enabled = 1) 
GROUP BY ancestor
       , CASE WHEN ancestor IS NULL
                  THEN table1.id
                  ELSE 0
         END
9
ypercubeᵀᴹ

Möglicherweise schnellere Version der vorherigen Lösung, falls Sie eine eindeutige Kennung in Tabelle1 haben (nehmen wir an, es ist Tabelle1.id):

SELECT `table1`.*, 
    GROUP_CONCAT(id SEPARATOR ',') AS `children_ids`,
    IF(ISNULL(ancestor),table1.id,NULL) as `do_not_group_on_null_ancestor`
FROM `table1` 
WHERE (enabled = 1) 
GROUP BY `ancestor`, `do_not_group_on_null_ancestor`
6
Stepan