2010-04-28 16 views
6

Estoy seguro de que esto tiene una respuesta muy simple, pero parece que no puedo encontrarlo (¡no estoy seguro de qué buscar!) . Un recuento/grupo estándar de consulta puede tener este aspecto:MYSQL: COUNT con GROUP BY, LEFT JOIN y WHERE cláusula no devuelve valores cero

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 

y esto funciona como se esperaba, devolviendo un 0 si no se encuentran filas. Sin embargo:

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 

sólo funciona si hay al menos una fila en table_1 y falla estrepitosamente devolver un conjunto de resultados vacío si hay cero filas. Realmente me gustaría que esto vuelva 0! Alguien me ilumine sobre esto? Se puede proporcionar cerveza a cambio si se encuentra en Londres ;-)

Respuesta

4

La razón por la que devuelve cero filas es que se está agrupando en un valor en la tabla_1. Como no hay valores en la tabla_1, no hay filas para devolver. Dicho de otra manera, si usted regresó t1.any_col en su consulta de cada grupo por así:

SELECT `t1`.`any_col`, COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 

Lo que se muestra para t1.any_col cuando no había filas? La única forma de lograr lo que desea es unir sus resultados con otra consulta que no comprueba filas en la tabla_1. En este ejemplo, estoy usando la vista INFORMATION_SCHEMA simplemente para tener algo contra lo que pueda consultar.

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 
UNION ALL 
SELECT 0 
FROM INFORMATION_SCHEMA.TABLES 
Where Not Exists(Select 1 From `table_1`) 
LIMIT 1 
+0

¿Por qué el primer ejemplo funciona bien entonces? Lo único que falta es la cláusula WHERE, todavía no puede haber filas y esto funcionará muy bien ... –

+0

@Paul Norman - El primer ejemplo funciona porque claramente hay filas en la tabla_1. El tercer ejemplo no funciona porque aparentemente no hay filas en la tabla_1 que tengan un valor 123 para 'another_column'. Si la consulta sin la agrupación no devuelve filas, no devolverá filas con la agrupación. – Thomas

3

Aquí es la mejor solución:

SELECT COUNT(*) FROM 
(SELECT `t2`.`name` 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col`) tmp 

Sólo se necesita para envolver SELECT COUNT(*) alrededor de la consulta.

El problema es que COUNT() cambia del significado "darme un recuento de las filas en el conjunto de resultados" a una función agregada que significa "darme un recuento de las filas para cada grupo que coinciden con mis criterios" cuando se utiliza con el GROUP BY cláusula. En su caso, dado que no hay filas para el grupo donde another_column = 123, no se devuelve nada.

Si envuelve eso en otro SELECT COUNT(*), está diciendo nuevamente, "denme un recuento de las filas en el conjunto de resultados".

En la primera consulta, COUNT() está trabajando con GROUP BY. Pero sin un criterio especificado, recibirá al menos una fila devuelta de la tabla_1. Dado que no hay registros table_2 correspondientes, NULL se evalúa a 0 para COUNT(). No use la primera consulta. Aunque devuelve lo que estás esperando, es solo por casualidad. Para que la consulta sea significativa, debe especificar criterios para t1.another_column en la cláusula WHERE.

La segunda consulta funciona porque está solicitando un recuento de filas del conjunto de resultados. Como no hay filas donde t1.another_column = 123, hay 0 filas devueltas, y COUNT() evalúa a 0.

+0

Esto lamentablemente solo me dice cuántos "grupos" únicos hay. Entonces, si solo hay un valor distintivo 'any_col' en' table_1', pero 5 filas de datos donde 'any_col' = 5 esto devolvería 1, no 5 según sea necesario (porque el SELECT anidado solo devolvería una fila). –

+0

@Paul, actualice su navegador. Yo había arreglado esto. Tenga en cuenta que COUNT() solo se usa en la consulta externa. –

+0

Hice ese cambio yo mismo, pero sigo pensando (o más bien lo he probado) que GROUP BY en la consulta anidada significa que solo se devolverá una fila si los únicos datos en la tabla tienen un único valor 'any_col' (es decir, si cada fila tiene 'any_col' = 5, la selección anidada devolverá solo una fila, como era de esperar, y luego se deduce que al contar estos datos, solo produce 1, no el 5 requerido. La solución anterior funciona de todos modos, ¡nunca pensé en eso! Gracias por toda la ayuda. ¡Es difícil ser claro en esta pequeña caja! –