42194


下記のテーブルA,テーブルBから、年齢の分布テーブルを求めるSQLが知りたいです。

テーブルA：ユーザIDと年齢のテーブル

ユーザID、年齢  
1,20  
2,21  
3,26  
4,68  
5,34  
6,16  
...

テーブルB：年齢の区分テーブル

区分ID、年齢下限、年齢上限  
1,0,10  
2,11,20  
3,21,30  
4,31,40  
5,41,50  
6,51,60  
7,61,70  
8,71,120  
..

欲しい年齢区分テーブルは以下を想定しております。

欲しいテーブル：各年齢区分にユーザが何人いるかのテーブル

区分ID,ユーザ人数,年齢範囲  
1,100,0-10  
2,20,11-20  
3,41,21-30  
5,77,31-40  
....

CASEやSUM,JOINを使用して出来るのではないかと思うのですが...  
ご教授お願いいたします。


CC BY-SA 3.0
2018-03-07T01:27:56.017
42179
2018-03-07T07:58:34.630
2018-03-07T04:11:26.737
24104
24104
question
sql
年齢分布テーブルを求めるSQL


このテーブル構成だとテーブルBのレコード数は多くて数十個かと思います。  
その前提で回答しますと、以下のように素直に相関サブクエリ記述して問題なく動作するかと思われます。

[code]

    INSERT INTO C (age_class_id, user_count, age_range)
    SELECT
            B.age_class_id AS age_class_id
    ,       (
                    SELECT
                            COUNT(*) AS user_count
                    FROM
                            A
                    WHERE
                            B.min_age <= A.age AND A.age <= B.max_age
            ) AS class_user_count
    ,
            (B.min_age || '-' || B.max_age) AS age_range 
    FROM B
    
[/code]

追記)  
もしユーザが０人の年齢区分のレコードを作成しなくてよいのであれば、以下のように INNER JOIN する方法になるかと思います。

[code]

    INSERT INTO C (age_class_id, user_count, age_range)
    SELECT
            B.age_class_id AS age_class_id
    ,       COUNT(*) AS class_user_count
    ,       (B.min_age || '-' || B.max_age) AS age_range
    FROM B
    INNER JOIN A
            ON A.age BETWEEN B.min_age  AND B.max_age
    GROUP BY
            B.age_class_id
    
[/code]

※ SQLite で確認したSQLですのでお使いのデータベースエンジンに合わせて書き換えてください。


CC BY-SA 3.0
2018-03-07T04:11:31.177
42184
2018-03-07T04:36:40.773
2018-03-07T04:36:40.773
27410
27410
42179
answer

[code]

    select *
    from テーブルA a
        join テーブルB b
            on a.年齢 between b.年齢下限 and b.年齢上限
    
[/code]


CC BY-SA 3.0
2018-03-07T04:18:34.210
42185
2018-03-07T07:20:41.110
2018-03-07T07:20:41.110
19110
27637
42179
answer


sa-yさんの回答とほぼ同じですが

[code]

    SELECT
      区分ID,
      COUNT(ユーザID) AS ユーザ人数,
      CONCAT(MIN(年齢下限), '-', MIN(年齢上限)) AS 年齢範囲
    FROM テーブルB
    LEFT OUTER JOIN テーブルA ON 年齢 BETWEEN 年齢下限 AND 年齢上限
    GROUP BY 区分ID;
    
[/code]

`LEFT OUTER JOIN`を使用すると0人の区分も得られ、ここを`INNER
JOIN`に変更すると0人の区分が省かれます。支障ないと思いますが`ユーザID`が`NULL`でないことを前提に集計してます。


CC BY-SA 3.0
2018-03-07T07:58:34.630
42194
2018-03-07T07:58:34.630
4236
42179
answer