2010-08-30 10 views
9
tabla de base de datos como

esta consulta0 Cuenta de regreso con el grupo mysql por

============================ 
= suburb_id | value 
= 1   | 2 
= 1   | 3 
= 2   | 4 
= 3   | 5 

es

SELECT COUNT(suburb_id) AS total, suburb_id 
    FROM suburbs 
where suburb_id IN (1,2,3,4) 
GROUP BY suburb_id 

Sin embargo, mientras yo funciono con esta pregunta, no da COUNT (suburb_id) = 0 cuando suburb_id = 0 porque en la tabla suburbios, no hay suburb_id 4, Quiero que esta consulta para devolver 0 para suburb_id = 4, al igual que

============================ 
= total  | suburb_id 
= 2   | 1 
= 1   | 2 
= 1   | 3 
= 0   | 4 
+0

¿Tienes otra tabla con información para todos los suburbios? ¿O es surburb 4 Sir Not-Appearing-In-This-Database? – Powerlord

Respuesta

10

Un GROUP BY necesita filas para trabajar, por lo que si no tiene filas para una categoría determinada, no obtendrá el recuento. Piense en la cláusula where como una limitación de las filas fuente antes de agruparse. La cláusula where no proporciona una lista de categorías para agrupar.

Lo que podría hacer es escribir una consulta para seleccionar las categorías (suburbios) y luego hacer el conteo en una subconsulta. (No estoy seguro de lo que el apoyo de MySQL para esto es como)

Algo así como:

SELECT 
    s.suburb_id, 
    (select count(*) from suburb_data d where d.suburb_id = s.suburb_id) as total 
FROM 
    suburb_table s 
WHERE 
    s.suburb_id in (1,2,3,4) 

(MSSQL, disculpas)

+0

+1 para el caso simple, pero cuando necesite combinar varias consultas más complicadas, vea mi respuesta. – Upgradingdave

+0

¡Esto era exactamente lo que estaba buscando! – thenetimp

1

Consulta:

select case 
     when total is null then 0 
     else total 
     end as total_with_zeroes, 
     suburb_id 
from (SELECT COUNT(suburb_id) AS total, suburb_id 
     FROM suburbs 
     where suburb_id IN (1,2,3,4) 
    GROUP BY suburb_id) as dt 
+1

Como no hay registros con 'suburb_id' como 4, la consulta interna no devolverá un NULL para que la expresión CASE capture. –

4

Este:

SELECT id, COUNT(suburb_id) 
FROM (
     SELECT 1 AS id 
     UNION ALL 
     SELECT 2 AS id 
     UNION ALL 
     SELECT 3 AS id 
     UNION ALL 
     SELECT 4 AS id 
     ) ids 
LEFT JOIN 
     suburbs s 
ON  s.suburb_id = ids.id 
GROUP BY 
     id 

o esto:

SELECT id, 
     (
     SELECT COUNT(*) 
     FROM suburb 
     WHERE suburb_id = id 
     ) 
FROM (
     SELECT 1 AS id 
     UNION ALL 
     SELECT 2 AS id 
     UNION ALL 
     SELECT 3 AS id 
     UNION ALL 
     SELECT 4 AS id 
     ) ids 

En este artículo se compara el rendimiento de los dos enfoques:

, a pesar de que no importa mucho en su caso, ya que se está consultando sólo 4 registros.

+0

Puke. Pero correcto. Mysql tiene tantas características funky "no estándar", ¿cómo es que no tiene un generador de serie todavía? Por cierto, para al menos algunos códigos de brevedad, puedes eliminar el 'ALL' de tus' UNION's (todos los valores son únicos y ya están ordenados, por lo que el resultado será el mismo con 'UNION') y eliminar todos menos el primero 'AS ID'. Y podría alinearlo: 'FROM (SELECT 1 AS id UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) ids'. – Bohemian

1

@ La solución de geofftnz funciona muy bien si todas las condiciones son simples, como en este caso. Pero solo tuve que resolver un problema similar para generar un informe donde cada columna en el informe es una consulta diferente. Cuando necesite combinar resultados de varias declaraciones select, entonces algo como esto podría funcionar.

Es posible que tenga que crear esta consulta mediante programación. El uso de combinaciones a la izquierda permite a la consulta devolver filas incluso si no hay coincidencias con suburb_id con una identificación dada. Si su base de datos lo permite (que la mayoría), se puede utilizar IFNULL para reemplazar nula con 0:

select IFNULL(a.count,0), IFNULL(b.count,0), IFNULL(c.count,0), IFNULL(d.count,0) 
from (select count(suburb_id) as count from suburbs where id=1 group by suburb_id) a, 
left join (select count(suburb_id) as count from suburbs where id=2 group by suburb_id) b on a.suburb_id=b.suburb_id 
left join (select count(suburb_id) as count from suburbs where id=3 group by suburb_id) c on a.suburb_id=c.suburb_id 
left join (select count(suburb_id) as count from suburbs where id=4 group by suburb_id) d on a.suburb_id=d.suburb_id; 

Lo bueno de esto es que (si es necesario) cada una "combinación izquierda" se puede usar un poco diferente (posiblemente bastante complejo) consulta.

responsabilidad: A los grandes conjuntos de datos, este tipo de consulta podría haber rendimiento no es bueno (no escribo lo suficientemente sql saber sin investigar más a fondo), pero al menos se debería dar resultados útiles ;-)