SQLで列値の出現を効率的にカウントする方法


166

学生のテーブルがあります:

id | age
--------
0  | 25
1  | 25
2  | 23

すべての学生をクエリし、同じ年齢の学生の数を数える追加の列を作成します。

id | age | count
----------------
0  | 25  | 2
1  | 25  | 2
2  | 23  | 1

これを行う最も効率的な方法は何ですか?サブクエリが遅くなることを恐れており、もっと良い方法があるかどうか疑問に思っています。ある?

回答:


255

これはうまくいくはずです:

SELECT age, count(age) 
  FROM Students 
 GROUP by age

idも必要な場合は、上記のようにサブクエリとして上記を含めることができます。

SELECT S.id, S.age, C.cnt
  FROM Students  S
       INNER JOIN (SELECT age, count(age) as cnt
                     FROM Students 
                    GROUP BY age) C ON S.age = C.age

2
2番目のクエリの場合、S.cntがないため、外側の選択はC.cntにある必要があります。そうしないと、エラーが発生します。無効な列名 'cnt'
KM。

1
select case_id、count(pgm_code)from pgm group from pgm_code; それは表現によるグループではないと言っています
リシャブ・アガルヴァル

26

Oracleを使用している場合は、アナリティクスと呼ばれる機能が役立ちます。次のようになります。

select id, age, count(*) over (partition by age) from students;

Oracleを使用していない場合は、カウントに戻って参加する必要があります。

select a.id, a.age, b.age_count
  from students a
  join (select age, count(*) as age_count
          from students
         group by age) b
    on a.age = b.age

2
参考までに、SQL Server 2005では、2番目のクエリは最初のクエリの実行コストのほぼ半分(SET SHOWPLAN_ALL ONを使用)で実行されます。最初のほうが良かったと思いましたが、オールドスクールのメンバーが勝ちました。
和基。

1
処理されるTOTAL ROW COUNTが異なるというだけの理由で、「古い学校の参加はそれを打ち負かしました」。2番目のクエリには、行の数を大幅に減らす可能性のある組み込みgroup-byがあります。最初のクエリにDISTINCTを追加してみてください: "select DISTINCT id、age、count(*)over(partition by age)from student"-比較できるはずです
quetzalcoatl

19

これが別の解決策です。これは非常に単純な構文を使用しています。受け入れられたソリューションの最初の例は、古いバージョンのMicrosoft SQL(つまり2000)では機能しませんでした。

SELECT age, count(*)
FROM Students 
GROUP by age
ORDER BY age

1
ただし、年齢でグループ化すると、カウントが2の25歳のエントリは1つしか得られません(実際には、カウントが2の2つのエントリと、上記の例では個別のIDが必要な場合)。
Ian

1
イアン、フィードバックをありがとう。MS SQL 2000 DBに対して申し立てを行いましたか?
ダミアン

7

私は次のようなことをします:

select
 A.id, A.age, B.count 
from 
 students A, 
 (select age, count(*) as count from students group by age) B
where A.age=B.age;

4
select s.id, s.age, c.count
from students s
inner join (
    select age, count(*) as count
    from students
    group by age
) c on s.age = c.age
order by id

1

「年齢」列のデータに同様のレコードがある場合(つまり、多くの人が25歳で、他の多くが32歳など)、各生徒に正しい数を揃えるのに混乱が生じます。それを避けるために、学生IDのテーブルにも参加しました。

SELECT S.id, S.age, C.cnt
FROM Students S 
INNER JOIN (SELECT id, age, count(age) as cnt  FROM Students GROUP BY student,age) 
C ON S.age = C.age *AND S.id = C.id*
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.