GROUP BY – do not group NULL

Estoy tratando de encontrar una forma de devolver los resultados usando el grupo por function.

GROUP BY funciona como se esperaba, pero mi pregunta es: ¿es posible tener un grupo ignorando el campo NULL? Para que no agrupe NULLs juntos porque todavía necesito todas las filas donde el campo especificado es NULL.

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

Así que ahora digamos que tengo 5 filas y el campo ancestro es NULL, me devuelve 1 fila … pero quiero las 5.

¿Quizás debería agregar algo a las columnas nulas para que sean únicas y agruparlas? Estaba buscando algún tipo de secuencia para usar en lugar de UUID () pero esto podría funcionar igual de bien.

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

Al agrupar por la columna Y , todas las filas para las cuales el valor en Y es NULL se agrupan juntas.

Este comportamiento está definido por el estándar SQL-2003 , aunque es ligeramente sorprendente porque NULL no es igual a NULL .

Puede solucionarlo agrupando en un valor diferente, alguna function (matemáticamente hablando) de los datos en su columna de agrupamiento.

Si tiene una columna X única, esto es fácil.


Entrada

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

Sin arreglo

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

Resultado:

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

Con arreglo

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

Resultado:

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

Echemos un vistazo más de cerca a cómo funciona esto

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

Resultado:

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

Si no tiene una columna única que pueda usar, puede intentar generar un valor de marcador de position único en su lugar. Dejaré esto como un ejercicio para el lector.

Tal vez una versión más rápida de la solución anterior en caso de que tenga un identificador único en la tabla 1 (supongamos que es table1.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` 
 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 

GROUP BY IFNULL(requinetworking_field, id)