web-dev-qa-db-ja.com

一部の列に集計関数を使用して、年齢範囲と性別でグループ化

Mysqlには、id、birth_year、および性別の患者テーブルがあります。次のテーブルは、id、patient_id [患者からのFK]、checkup_dateを持つトランザクションです。年齢の範囲内のすべての男性と女性の健康診断の数が得られるように、行を選択する必要があります。

次の表形式の結果を達成するためにクエリを実行するにはどうすればよいですか?

20歳未満:男性:10回、女性:15回

21〜30、男性:20回、女性:35回

31〜40、男性:30回、女性:45回

.... ....... ......... ....... ........ ..........

81〜90、男性:10回、女性:6回

90歳以上、男性:0回、女性:4回

ありがとうございました。

2
sangam

2つのオプション。

a)サブクエリを使用する

select 
  concat(10*floor(age/10), '-', 10*floor(age/10) + 10) as `range`, 
  gender, 
  count(*) as count 
from (
  select 
    *, 
    TIMESTAMPDIFF(YEAR,birth_year,CURDATE()) AS age
  from 
    transaction left join patient on patient_id = patient.id
) as t group by `range`, gender;

与える

+-------+--------+-------+
| range | gender | count |
+-------+--------+-------+
| 0-10  | m      |     2 |
| 10-20 | m      |     1 |
| 20-30 | m      |     3 |
| 30-40 | f      |     2 |
| 30-40 | m      |     2 |
| 50-60 | f      |     1 |
| 50-60 | m      |     1 |
| 60-70 | f      |     5 |
| 60-70 | m      |     3 |
| 70-80 | f      |     1 |
| 70-80 | m      |     6 |
+-------+--------+-------+

b)最初に年齢でグループ化し、次に適用範囲内でグループ化します。

ORMを使用する場合、サブクエリを実行するのは簡単ではないので、これは良いアイデアかもしれません。

パフォーマンスの観点:平均的な人間が100年間住んでいることを考えると、アプリケーションで簡単にループできる最大200のレコード(男性100と女性100)が存在する可能性があります。

select 
  gender, 
  TIMESTAMPDIFF(YEAR,birth_year,CURDATE()) AS age,
  count(*)
from 
  transaction left join patient on patient_id = patient.id
group by age, gender

与える

+--------+------+----------+
| gender | age  | count(*) |
+--------+------+----------+
| m      |    4 |        2 |
| m      |   14 |        1 |
| m      |   24 |        3 |
| f      |   34 |        2 |
| m      |   34 |        2 |
| f      |   54 |        1 |
| m      |   54 |        1 |
| f      |   64 |        5 |
| m      |   64 |        3 |
| f      |   74 |        1 |
| m      |   74 |        6 |
+--------+------+----------+
4
bibstha