relacionadas - ejemplos de consultas en mysql
¿Cómo obtener múltiples cuentas con una consulta SQL? (9)
Basándose en otras respuestas publicadas.
Ambos producirán los valores correctos:
select distributor_id,
count(*) total,
sum(case when level = ''exec'' then 1 else 0 end) ExecCount,
sum(case when level = ''personal'' then 1 else 0 end) PersonalCount
from yourtable
group by distributor_id
SELECT a.distributor_id,
(SELECT COUNT(*) FROM myTable WHERE level=''personal'' and distributor_id = a.distributor_id) as PersonalCount,
(SELECT COUNT(*) FROM myTable WHERE level=''exec'' and distributor_id = a.distributor_id) as ExecCount,
(SELECT COUNT(*) FROM myTable WHERE distributor_id = a.distributor_id) as TotalCount
FROM myTable a ;
Sin embargo, el rendimiento es bastante diferente, lo que obviamente será más relevante a medida que crezca la cantidad de datos.
Descubrí que, suponiendo que no se definieran índices en la tabla, la consulta que utiliza los SUM haría un solo análisis de la tabla, mientras que la consulta con los COUNT realizaría varios análisis de la tabla.
Como ejemplo, ejecute el siguiente script:
IF OBJECT_ID (N''t1'', N''U'') IS NOT NULL
drop table t1
create table t1 (f1 int)
insert into t1 values (1)
insert into t1 values (1)
insert into t1 values (2)
insert into t1 values (2)
insert into t1 values (2)
insert into t1 values (3)
insert into t1 values (3)
insert into t1 values (3)
insert into t1 values (3)
insert into t1 values (4)
insert into t1 values (4)
insert into t1 values (4)
insert into t1 values (4)
insert into t1 values (4)
SELECT SUM(CASE WHEN f1 = 1 THEN 1 else 0 end),
SUM(CASE WHEN f1 = 2 THEN 1 else 0 end),
SUM(CASE WHEN f1 = 3 THEN 1 else 0 end),
SUM(CASE WHEN f1 = 4 THEN 1 else 0 end)
from t1
SELECT
(select COUNT(*) from t1 where f1 = 1),
(select COUNT(*) from t1 where f1 = 2),
(select COUNT(*) from t1 where f1 = 3),
(select COUNT(*) from t1 where f1 = 4)
Resalte las 2 declaraciones SELECT y haga clic en el icono Mostrar el plan de ejecución estimado. Verá que la primera instrucción hará una exploración de la tabla y la segunda hará 4. Obviamente, una exploración de la tabla es mejor que 4.
Agregar un índice agrupado también es interesante. P.ej
Create clustered index t1f1 on t1(f1);
Update Statistics t1;
El primer SELECCIONAR anterior hará una sola Exploración de índice agrupado. El segundo SELECT realizará 4 búsquedas de índice agrupado, pero aún son más costosas que una sola exploración de índice agrupado. Probé lo mismo en una tabla con 8 millones de filas y el segundo SELECT todavía era mucho más caro.
Me pregunto cómo escribir esta consulta.
Sé que esta sintaxis real es falsa, pero te ayudará a entender lo que quiero. Lo necesito en este formato, porque es parte de una consulta mucho más grande.
SELECT distributor_id,
COUNT(*) AS TOTAL,
COUNT(*) WHERE level = ''exec'',
COUNT(*) WHERE level = ''personal''
Necesito que todo esto devuelto en una consulta.
Además, debe estar en una fila, por lo que no funcionará lo siguiente:
''SELECT distributor_id, COUNT(*)
GROUP BY distributor_id''
Basado en la respuesta aceptada de Bluefeet con un matiz adicional usando OVER ()
select distributor_id,
count(*) total,
sum(case when level = ''exec'' then 1 else 0 end) OVER() ExecCount,
sum(case when level = ''personal'' then 1 else 0 end) OVER () PersonalCount
from yourtable
group by distributor_id
El uso de OVER()
sin nada en el () le dará el recuento total de todo el conjunto de datos.
Bueno, si debe tener todo en una consulta, podría hacer una unión:
SELECT distributor_id, COUNT() FROM ... UNION
SELECT COUNT() AS EXEC_COUNT FROM ... WHERE level = ''exec'' UNION
SELECT COUNT(*) AS PERSONAL_COUNT FROM ... WHERE level = ''personal'';
O, si puedes hacerlo después de procesar:
SELECT distributor_id, COUNT(*) FROM ... GROUP BY level;
Obtendrá el recuento de cada nivel y deberá resumirlos todos para obtener el total.
Creo que esto también puede funcionar para que select count(*) as anc,(select count(*) from Patient where sex=''F'')as patientF,(select count(*) from Patient where sex=''M'') as patientM from anc
y también puede seleccionar y contar tablas relacionadas como esta, select count(*) as anc,(select count(*) from Patient where Patient.Id=anc.PatientId)as patientF,(select count(*) from Patient where sex=''M'') as patientM from anc
Hago algo como esto donde le doy a cada tabla un nombre de cadena para identificarlo en la columna A y un recuento para la columna. Luego los uní a todos para que apilen. El resultado es bastante en mi opinión, no estoy seguro de cuán eficiente es en comparación con otras opciones, pero me dio lo que necesitaba.
select ''table1'', count (*) from table1
union select ''table2'', count (*) from table2
union select ''table3'', count (*) from table3
union select ''table4'', count (*) from table4
union select ''table5'', count (*) from table5
union select ''table6'', count (*) from table6
union select ''table7'', count (*) from table7;
Resultado:
-------------------
| String | Count |
-------------------
| table1 | 123 |
| table2 | 234 |
| table3 | 345 |
| table4 | 456 |
| table5 | 567 |
-------------------
Para mysql esto se puede reducir a
select distributor_id,
count(*) total,
sum(level = ''exec'') ExecCount,
sum(level = ''personal'') PersonalCount
from yourtable
group by distributor_id
Puede utilizar una sentencia CASE
con una función agregada. Esto es básicamente lo mismo que una función PIVOT
en algunos RDBMS:
select distributor_id,
count(*) total,
sum(case when level = ''exec'' then 1 else 0 end) ExecCount,
sum(case when level = ''personal'' then 1 else 0 end) PersonalCount
from yourtable
group by distributor_id
Una forma que funciona seguro
SELECT a.distributor_id,
(SELECT COUNT(*) FROM myTable WHERE level=''personal'' and distributor_id = a.distributor_id) as PersonalCount,
(SELECT COUNT(*) FROM myTable WHERE level=''exec'' and distributor_id = a.distributor_id) as ExecCount,
(SELECT COUNT(*) FROM myTable WHERE distributor_id = a.distributor_id) as TotalCount
FROM (SELECT DISTINCT distributor_id FROM myTable) a ;
EDITAR:
Vea el desglose de rendimiento de @KevinBalmforth para saber por qué probablemente no quiera usar este método y en su lugar debería optar por la respuesta de @ bluefeet Dejo esto para que la gente pueda entender sus opciones.
SELECT
distributor_id,
COUNT(*) AS TOTAL,
COUNT(IF(level=''exec'',1,null)),
COUNT(IF(level=''personal'',1,null))
FROM sometable;
COUNT
solo cuenta valores non null
y el DECODE
devolverá un valor no nulo 1
solo si su condición se cumple.