Come ottenere più conteggi con una query SQL?

Mi sto chiedendo come scrivere questa query.

So che questa syntax attuale è falsa, ma ti aiuterà a capire cosa voglio. Ne ho bisogno in questo formato, perché fa parte di una query molto più ampia.

SELECT distributor_id, COUNT(*) AS TOTAL, COUNT(*) WHERE level = 'exec', COUNT(*) WHERE level = 'personal' 

Ho bisogno che tutto questo venga restituito in una query.

Inoltre, deve essere in una riga, quindi il seguente non funzionerà:

 'SELECT distributor_id, COUNT(*) GROUP BY distributor_id' 

È ansible utilizzare un’istruzione CASE con una funzione di aggregazione. In pratica è la stessa cosa di una funzione PIVOT in alcuni 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 

Un modo che funziona di sicuro

 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 ; 

MODIFICARE:
Vedi l’analisi delle prestazioni di @ KevinBalmforth per il motivo per cui probabilmente non vuoi usare questo metodo e invece dovresti optare per la risposta di @ bluefeet. Sto lasciando questo così le persone possono capire le loro opzioni.

 SELECT distributor_id, COUNT(*) AS TOTAL, COUNT(IF(level='exec',1,null)), COUNT(IF(level='personal',1,null)) FROM sometable; 

COUNT conta solo valori non null e DECODE restituisce valore non nullo 1 solo se la condizione è soddisfatta.

Per mysql questo può essere ridotto a

 select distributor_id, count(*) total, sum(level = 'exec') ExecCount, sum(level = 'personal') PersonalCount from yourtable group by distributor_id 

Basandosi su altre risposte postate.

Entrambi produrranno i giusti valori:

 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 ; 

Tuttavia, le prestazioni sono abbastanza diverse, il che sarà ovviamente più rilevante con l’aumentare della quantità di dati.

Ho scoperto che, supponendo che non fossero stati definiti indici sulla tabella, la query che utilizzava SUMs avrebbe eseguito una scansione di una singola tabella, mentre la query con i COUNT avrebbe eseguito più scansioni di tabelle.

Ad esempio, esegui il seguente 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) 

Evidenzia le 2 istruzioni SELECT e fai clic sull’icona Visualizza piano di esecuzione stimato. Vedrai che la prima istruzione farà una scansione della tabella e la seconda farà 4. Ovviamente una scansione della tabella è migliore di 4.

Anche l’aggiunta di un indice cluster è interessante. Per esempio

 Create clustered index t1f1 on t1(f1); Update Statistics t1; 

Il primo SELECT sopra farà una singola scansione di indice raggruppata. Il secondo SELECT farà 4 Seek Index in cluster, ma sono ancora più costosi di una singola scansione in cluster. Ho provato la stessa cosa su un tavolo con 8 milioni di file e il secondo SELECT era ancora molto più costoso.

Bene, se devi avere tutto in un’unica query, potresti fare un sindacato:

 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'; 

Oppure, se puoi fare dopo l’elaborazione:

 SELECT distributor_id, COUNT(*) FROM ... GROUP BY level; 

Otterrai il conteggio per ogni livello e dovrai sumrli tutti per ottenere il totale.

Faccio qualcosa di simile a questo in cui do a ogni tabella solo un nome di stringa per identificarlo nella colonna A e un conteggio per la colonna. Poi li unisco tutti in modo che si impilino. Il risultato è piuttosto secondo me, non so quanto sia efficiente rispetto ad altre opzioni, ma mi ha dato ciò di cui avevo bisogno.

 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; 

Risultato:

 ------------------- | String | Count | ------------------- | table1 | 123 | | table2 | 234 | | table3 | 345 | | table4 | 456 | | table5 | 567 | ------------------- 

Basato sulla risposta accettata di Bluefeet con una sfumatura aggiunta che utilizza 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 

Usando OVER() con niente in () otterrai il conteggio totale per l’intero set di dati.

Penso che questo select count(*) as anc,(select count(*) from Patient where sex='F')as patientF,(select count(*) from Patient where sex='M') as patientM from anc anche per te select count(*) as anc,(select count(*) from Patient where sex='F')as patientF,(select count(*) from Patient where sex='M') as patientM from anc

e inoltre è ansible selezionare e contare tabelle correlate come questo 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