427

このクエリをどのように書くのか疑問に思っています。

この実際の構文が偽物であることは知っていますが、私が何を望んでいるのかを理解するのに役立ちます。これははるかに大きなクエリの一部であるため、この形式で必要です。

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

これをすべて1つのクエリで返す必要があります。

また、1行にする必要があるため、以下は機能しません。

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

10 に答える 10

921

CASE集計関数でステートメントを使用できます。PIVOTこれは基本的に、一部のRDBMSの関数と同じです。

SELECT distributor_id,
    count(*) AS total,
    sum(case when level = 'exec' then 1 else 0 end) AS ExecCount,
    sum(case when level = 'personal' then 1 else 0 end) AS PersonalCount
FROM yourtable
GROUP BY distributor_id
于 2012-10-08T21:07:34.047 に答える
112

確実に機能する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 ;

編集:
この方法を使用したくない理由については、@ KevinBalmforthのパフォーマンスの内訳を参照してください。代わりに、@Taryn♦の回答を選択する必要があります。人々が彼らの選択肢を理解できるように、私はこれを残します。

于 2012-10-08T21:03:31.023 に答える
52
SELECT 
    distributor_id, 
    COUNT(*) AS TOTAL, 
    COUNT(IF(level='exec',1,null)),
    COUNT(IF(level='personal',1,null))
FROM sometable;

COUNTnon null値のみをカウントし、条件が満たされた場合にのみDECODEnull以外の値を返します。1

于 2012-10-08T21:05:21.163 に答える
40

他の投稿された回答に基づいて構築します。

これらは両方とも正しい値を生成します。

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ステートメントを強調表示し、[推定実行プランの表示]アイコンをクリックします。最初のステートメントが1つのテーブルスキャンを実行し、2番目のステートメントが4を実行することがわかります。明らかに、1つのテーブルスキャンは4よりも優れています。

クラスタ化されたインデックスを追加することも興味深いです。例えば

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

上記の最初のSELECTは、単一のクラスター化インデックススキャンを実行します。2番目のSELECTは4つのクラスター化インデックスシークを実行しますが、それでも単一のクラスター化インデックススキャンよりもコストがかかります。800万行のテーブルで同じことを試しましたが、2番目のSELECTはまだはるかに高価でした。

于 2015-12-03T16:02:52.913 に答える
28

MySQLの場合、これは次のように短縮できます。

SELECT distributor_id,
    COUNT(*) total,
    SUM(level = 'exec') ExecCount,
    SUM(level = 'personal') PersonalCount
FROM yourtable
GROUP BY distributor_id
于 2015-12-03T16:12:57.523 に答える
11

さて、すべてを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;

各レベルのカウントを取得し、合計を取得するにはそれらをすべて合計する必要があります。

于 2012-10-08T21:03:50.757 に答える
6

私はこのようなことを行い、各テーブルに列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   |
-------------------
于 2017-09-20T19:07:36.807 に答える
3

Bluefeetが受け入れた応答に基づいて、以下を使用してニュアンスを追加しました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

OVER()()を何も指定せずに使用すると、データセット全体の合計数がわかります。

于 2017-11-09T19:15:05.320 に答える
1

これもあなたのために働くことができると思います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

于 2018-04-13T07:10:58.483 に答える
0

Oracleでは、次のようなことを行います

SELECT
    (SELECT COUNT(*) FROM schema.table1),
    (SELECT COUNT(*) FROM schema.table2),
    ...
    (SELECT COUNT(*) FROM schema.tableN)
FROM DUAL;
于 2022-03-04T12:53:57.807 に答える