このクエリの書き方は疑問に思います。
私はこの実際の構文が偽であることを知っていますが、それはあなたが私が欲しいものを理解するのを助けるでしょう。これはもっと大きなクエリの一部なので、このフォーマットで必要です。
SELECT distributor_id,
COUNT(*) AS TOTAL,
COUNT(*) WHERE level = 'exec',
COUNT(*) WHERE level = 'personal'
これらすべてを1回のクエリで返す必要があります。
また、それは一列に並んでいる必要があるので、以下はうまくいきません。
'SELECT distributor_id, COUNT(*)
GROUP BY distributor_id'
集約関数と一緒にCASE
ステートメントを使用できます。これは基本的にいくつかのRDBMSのPIVOT
関数と同じものです。
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
確実に機能する1つの方法
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 ;
編集:
なぜこのメソッドを使用したくない場合があり、代わりに@ bluefeetの回答を選択すべきかについては、@ KevinBalmforthのパフォーマンスの詳細を参照してください。人々が彼らの選択肢を理解することができるように、私はこれを残します。
SELECT
distributor_id,
COUNT(*) AS TOTAL,
COUNT(IF(level='exec',1,null)),
COUNT(IF(level='personal',1,null))
FROM sometable;
COUNT
はnon null
値のみをカウントし、DECODE
は条件が満たされた場合にのみnull以外の値1
を返します。
他の投稿された回答を基にしています。
どちらも正しい値を生成します。
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 ;
ただし、パフォーマンスはかなり異なります。データ量が増えるにつれて、パフォーマンスは明らかに向上します。
テーブルにインデックスが定義されていないと仮定すると、SUMを使用したクエリは単一のテーブルスキャンを実行し、COUNTを使用したクエリは複数のテーブルスキャンを実行します。
例として、次のスクリプトを実行します。
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)
2つのSELECTステートメントを強調表示して、[Display Estimated Execution Plan]アイコンをクリックします。最初のステートメントが1回のテーブルスキャンを実行し、2番目のステートメントが4回のテーブルスキャンを実行することがわかります。明らかに、1回のテーブルスキャンは4回よりも優れています。
クラスタ化インデックスを追加することも興味深いです。例えば。
Create clustered index t1f1 on t1(f1);
Update Statistics t1;
上記の最初のSELECTは、単一のクラスタ化インデックススキャンを実行します。 2番目のSELECTは4つのクラスタ化インデックスシークを行いますが、それでも単一のクラスタ化インデックススキャンよりも高価です。私は800万行のテーブルで同じことを試しましたが、2番目のSELECTはまだもっとずっと高価でした。
MySQLの場合、これは短くすることができます
select distributor_id,
count(*) total,
sum(level = 'exec') ExecCount,
sum(level = 'personal') PersonalCount
from yourtable
group by distributor_id
1つのクエリにすべて含める必要がある場合は、結合を実行できます。
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';
あるいは、処理後にできること
SELECT distributor_id, COUNT(*) FROM ... GROUP BY level;
あなたは各レベルのカウントを取得し、合計を取得するためにそれらをすべて合計する必要があります。
このようにして、各テーブルに列Aで識別するための文字列名と、列の数を指定します。それから私はそれらを積み重ねるようにそれらすべてを結合します。結果は私の意見ではかなりです - それが他のオプションと比較してどれほど効率的であるかわからないが、それは私が必要としているものを私に得ました。
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;
結果:
-------------------
| String | Count |
-------------------
| table1 | 123 |
| table2 | 234 |
| table3 | 345 |
| table4 | 456 |
| table5 | 567 |
-------------------
OVER()を使用してニュアンスを追加したBluefeetの受け入れられた応答に基づく
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
()に何も指定せずにOVER()
を使用すると、データセット全体の総数がわかります。
私はこれもあなたのために働くことができると思いますselect count(*) as anc,(select count(*) from Patient where sex='F')as patientF,(select count(*) from Patient where sex='M') as patientM from anc
また、このように関連するテーブルを選択して数えることができます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