Opierając się na innych opublikowanych odpowiedziach.
Oba z nich wygenerują prawidłowe wartości:
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 ;
Jednak wydajność jest zupełnie inna, co oczywiście będzie bardziej odpowiednie w miarę wzrostu ilości danych.
Odkryłem, że przy założeniu braku indeksów w tabeli, zapytanie wykorzystujące SUMy wykonałoby skanowanie pojedynczej tabeli, podczas gdy zapytanie z LICZNIKAMI wykonałoby wiele skanów tabeli.
Na przykład uruchom następujący skrypt:
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)
Podświetl 2 instrukcje SELECT i kliknij ikonę Wyświetl szacowany plan wykonania. Zobaczysz, że pierwsza instrukcja wykona jedno skanowanie tabeli, a druga zrobi 4. Oczywiście jedno skanowanie tabeli jest lepsze niż 4.
Interesujące jest także dodanie indeksu klastrowego. Na przykład
Create clustered index t1f1 on t1(f1);
Update Statistics t1;
Pierwszy WYBÓR powyżej wykona pojedyncze skanowanie indeksu klastrowanego. Drugi WYBÓR wykona 4 Wyszukiwanie indeksów klastrowych, ale są one nadal droższe niż pojedyncze skanowanie indeksów klastrowych. Próbowałem tego samego na stole z 8 milionami wierszy, a drugi SELECT był wciąż znacznie droższy.
SELECT distributor_id, COUNT(*) AS TOTAL, COUNT(*) WHERE level = 'exec', COUNT(*) WHERE level = 'personal'