2009-05-20 33 views
8

Quiero contar tanto el número total de registros en una tabla como el número total de registros que coinciden con ciertas condiciones. Puedo hacer esto con dos consultas separadas:dos consultas SQL COUNT()?

SELECT COUNT(*) AS TotalCount FROM MyTable; 
SELECT COUNT(*) AS QualifiedCount FROM MyTable 
    {possible JOIN(s) as well e.g. JOIN MyOtherTable mot ON MyTable.id=mot.id} 
    WHERE {conditions}; 

¿Hay una manera de combinar estos en una consulta para que consigo dos campos en una fila?

SELECT {something} AS TotalCount, 
    {something else} AS QualifiedCount 
    FROM MyTable {possible JOIN(s)} WHERE {some conditions} 

Si no es así, puedo emitir dos consultas y se envuelven en una transacción para que sean coherentes, pero esperaba hacerlo con uno.

editar: Estoy más preocupado por la atomicidad; si hay dos instrucciones sub-SELECT necesarias, eso está bien, siempre y cuando haya un INSERT proveniente de alguna parte, las dos respuestas no sean inconsistentes.

edit 2: Las respuestas de CASE son útiles pero en mi caso específico, las condiciones pueden incluir un JOIN con otra tabla (olvidé mencionar eso en mi publicación original, lo siento) así que supongo que ese enfoque no funcionará .

+0

¿Qué tipo de base de datos está utilizando? – Andomar

+0

MySQL, pero me gustaría saberlo en general si es bastante sencillo –

+0

Relacionado pero no con la solución: también puede usar para obtener los recuentos de tablas más grandes. SELECCIONAR SQL_CALC_FOUND_ROWSFROM MyTable; SELECCIONE FOUND_ROWS(); SELECCIONAR SQL_CALC_FOUND_ROWSFROM MyTable DONDE {condiciones}; SELECCIONE FOUND_ROWS(); –

Respuesta

22

Una forma es unirse a la mesa contra sí misma:

select 
    count(*) as TotalCount, 
    count(s.id) as QualifiedCount 
from 
    MyTable a 
left join 
    MyTable s on s.id = a.id and {some conditions} 

Otra forma es utilizar subconsultas:

select 
    (select count(*) from Mytable) as TotalCount, 
    (select count(*) from Mytable where {some conditions}) as QualifiedCount 

o puede poner las condiciones en un caso:

select 
    count(*) as TotalCount, 
    sum(case when {some conditions} then 1 else 0 end) as QualifiedCount 
from 
    MyTable 

Relacionados:

SQL Combining several SELECT results

+0

La autocombinación maneja el caso donde hay otras uniones en las condiciones. –

19

en SQL Server o MySQL, se puede hacer eso con una instrucción CASE:

select 
    count(*) as TotalCount, 
    sum(case when {conditions} then 1 else 0 end) as QualifiedCount 
from MyTable 

Editar: Esto también funciona si se utiliza una combinación en la condición:

select 
    count(*) as TotalCount, 
    sum(case when {conditions} then 1 else 0 end) as QualifiedCount 
from MyTable t 
left join MyChair c on c.TableId = t.Id 
group by t.id, t.[othercolums] 

El GROUP BY está ahí para garantizar que solo encuentre una fila de la tabla principal.

+1

Solo quiero señalar que este ejemplo funcionará mucho mejor que cualquier unión o unión ya que solo tiene que evaluar la tabla en cuestión una vez – kscott

+0

Me gusta esta técnica, es elegante. –

+0

es esa sintaxis "Alias ​​= Expresión" particular para SqlServer/MySQL o es bastante general? –

7

si solo está contando filas, puede usar las consultas anidadas.

select 
    (SELECT COUNT(*) AS TotalCount FROM MyTable) as a, 
    (SELECT COUNT(*) AS QualifiedCount FROM MyTable WHERE {conditions}) as b 
+0

Acepto que esta es la mejor manera de obtener el resultado que te da la gana y que se te debe entregar al mismo tiempo que las ejecuciones por separado. –

+0

Esta consulta le dará la respuesta, pero el costo de dos declaraciones seleccionadas y la cláusula where hacen que la solución CASE sea más eficiente – kscott

+0

+1 y editada para formatear, ¡espero que no le importe! – Andomar

0

MySQL no cuenta NULL, por lo que esto debería funcionar también:

SELECT count(*) AS TotalCount, 
    count(if(field = value, field, null)) AS QualifiedCount 
    FROM MyTable {possible JOIN(s)} WHERE {some conditions} 

que funciona bien si el campo QuailifiedCount proviene de un LEFT JOIN y sólo se preocupan si existe. Para obtener la cantidad de usuarios y la cantidad de usuarios que completaron su dirección:

SELECT count(user.id) as NumUsers, count(address.id) as NumAddresses 
    FROM Users 
    LEFT JOIN Address on User.address_id = Address.id;