tablas relacionadas multitablas ejemplos datos consultas consultar consulta complejas mysql sql join count group-by

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.