it-swarm.com.de

Wie bekomme ich mehrere Zähler mit einer SQL-Abfrage?

Ich frage mich, wie ich diese Abfrage schreiben soll.

Ich weiß, dass diese Syntax falsch ist, aber sie wird Ihnen helfen zu verstehen, was ich will. Ich brauche es in diesem Format, weil es Teil einer viel größeren Abfrage ist.

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

Ich brauche das alles in einer Abfrage zurück.

Außerdem muss es in einer Reihe stehen, damit Folgendes nicht funktioniert:

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

Sie können eine CASE -Anweisung mit einer Aggregatfunktion verwenden. Dies ist im Grunde das Gleiche wie eine PIVOT -Funktion in einigen 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
575
Taryn

Ein Weg, der sicher funktioniert

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 ;

EDIT:
Sehen Sie sich die Aufschlüsselung der Leistung von @ KevinBalmforth an, warum Sie diese Methode wahrscheinlich nicht verwenden möchten, und entscheiden Sie sich stattdessen für die Antwort von @ bluefeet. Ich lasse das, damit die Leute ihre Optionen verstehen können.

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

COUNT zählt nur non null Werte und DECODE liefert nur dann einen Wert ungleich Null 1, wenn Ihre Bedingung erfüllt ist.

36
Majid Laissi

Aufbauend auf anderen Antworten.

Beides ergibt die richtigen Werte:

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 ; 

Die Leistung ist jedoch sehr unterschiedlich, was offensichtlich mit zunehmender Datenmenge relevanter wird.

Unter der Annahme, dass keine Indizes für die Tabelle definiert wurden, würde die Abfrage mit den SUMs einen einzelnen Tabellenscan ausführen, während die Abfrage mit den COUNTs mehrere Tabellenscans ausführen würde.

Führen Sie beispielsweise das folgende Skript aus:

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)

Markieren Sie die 2 SELECT-Anweisungen und klicken Sie auf das Symbol Geschätzten Ausführungsplan anzeigen. Sie werden sehen, dass die erste Anweisung einen Tabellenscan und die zweite einen 4. durchführen wird. Offensichtlich ist ein Tabellenscan besser als 4.

Interessant ist auch das Hinzufügen eines Clustered-Index. Z.B.

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

Das erste SELECT oben führt einen einzelnen Clustered-Index-Scan durch. Das zweite SELECT führt 4 Clustered-Index-Suchvorgänge durch, die jedoch immer noch teurer sind als ein einzelner Clustered-Index-Suchvorgang. Ich habe dasselbe an einem Tisch mit 8 Millionen Zeilen versucht und das zweite SELECT war immer noch viel teurer.

22
Kevin Balmforth

Für MySQL kann dies verkürzt werden

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

Nun, wenn Sie alles in einer Abfrage haben müssen, können Sie eine Vereinigung durchführen:

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

Oder, wenn Sie nach der Verarbeitung tun können:

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

Sie erhalten die Anzahl für jedes Level und müssen sie alle aufsummieren, um die Gesamtsumme zu erhalten.

10
CrazyCasta

Ich mache so etwas, indem ich jeder Tabelle einen String-Namen gebe, um sie in Spalte A zu identifizieren, und eine Anzahl für die Spalte. Dann verbinde ich sie alle, damit sie stapeln. Das Ergebnis ist meiner Meinung nach ziemlich gut - ich bin mir nicht sicher, wie effizient es im Vergleich zu anderen Optionen ist, aber es hat mir das gebracht, was ich brauchte.

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;

Ergebnis:

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

Basierend auf Bluefeets akzeptierter Antwort mit einer zusätzlichen Nuance unter Verwendung von 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

Wenn Sie OVER() verwenden und nichts in () steht, erhalten Sie die Gesamtzahl für den gesamten Datensatz.

2
mentorrory

Ich denke das kann auch bei dir funktionieren select count(*) as anc,(select count(*) from Patient where sex='F')as patientF,(select count(*) from Patient where sex='M') as patientM from anc

und auch Sie können verwandte Tabellen wie diese auswählen und zählen 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

1
Sinte