質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

5回答

4251閲覧

体重ヒストグラムのSQL文

shiono

総合スコア7

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2017/11/14 14:28

以下のテーブルを基に体重ヒストグラムを作成したいです

tbl_student
組 名前 体重
1 a 38
1 b 52
1 c 56
1 d 62
2 e 45
2 f 65
2 g 78

このテーブルを集計し、以下の形にしたいです
tbl_weight_histogram
組 体重レンジ 人数
1 30 1
1 40 0
1 50 2
1 60 1
2 30 0
2 40 1
2 50 0
2 60 2

・体重レンジは30台、40台、50台、60台以上とする
・人数0人の場合も0件としてカウントする

特に2つ目の条件で困っております
外部テーブルを用意するのは構いません
どなたかご助言よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SVC34

2017/11/14 20:44

DBMSは何を使用していますか
guest

回答5

0

図でイメージするOracleのSQL全集 第1回 さまざまな結合
https://blogs.oracle.com/otnjp/oracle-sql-image-001
の「Partitioned Outer Join」を見ながら
SQLFiddleのOracle11gR2環境で作ってみました :-)

sql

1with RangeTable(体重レンジ,下限,上限) as( 2select 30, 0, 39 from dual union 3select 40,40, 49 from dual union 4select 50,50, 59 from dual union 5select 60,60,999 from dual), 6tbl_student(,名前,体重) as( 7select 1,'a',38 from dual union 8select 1,'b',52 from dual union 9select 1,'c',56 from dual union 10select 1,'d',62 from dual union 11select 2,'e',45 from dual union 12select 2,'f',65 from dual union 13select 2,'g',78 from dual) 14select b.,a.体重レンジ,count(b.体重) as 人数 15 from RangeTable a 16 Left Join tbl_student b 17partition by(b.) 18 on b.体重 between a.下限 and a.上限 19group by b.,a.体重レンジ 20order by b.,a.体重レンジ; 21 22|| 体重レンジ | 人数 | 23|----|------------|------| 24| 1 | 30 | 1 | 25| 1 | 40 | 0 | 26| 1 | 50 | 2 | 27| 1 | 60 | 1 | 28| 2 | 30 | 0 | 29| 2 | 40 | 1 | 30| 2 | 50 | 0 | 31| 2 | 60 | 2 |

投稿2017/11/17 21:00

編集2020/07/26 08:37
AketiJyuuzou

総合スコア1147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

図でイメージするOracleのSQL全集 第8回 PivotとUnPivot
https://blogs.oracle.com/otnjp/oracle-sql-image-008
を見ながら、SQLFiddleのOracle11gR2環境で作ってみました :-)

sql

1with tbl_student(,名前,体重) as( 2select 1,'a',38 from dual union 3select 1,'b',52 from dual union 4select 1,'c',56 from dual union 5select 1,'d',62 from dual union 6select 2,'e',45 from dual union 7select 2,'f',65 from dual union 8select 2,'g',78 from dual), 9tmp as( 10select, 11count(case when 体重 between 0 and 39 then 1 end) as cnt1, 12count(case when 体重 between 40 and 49 then 1 end) as cnt2, 13count(case when 体重 between 50 and 59 then 1 end) as cnt3, 14count(case when 体重 between 60 and 999 then 1 end) as cnt4 15 from tbl_student 16group by) 17select * 18 from tmp 19UnPivot(人数 for 体重レンジ 20 in(cnt1 as 30, 21 cnt2 as 40, 22 cnt3 as 50, 23 cnt4 as 60)) 24order by,体重レンジ; 25 26|| 体重レンジ | 人数 | 27|----|------------|------| 28| 1 | 30 | 1 | 29| 1 | 40 | 0 | 30| 1 | 50 | 2 | 31| 1 | 60 | 1 | 32| 2 | 30 | 0 | 33| 2 | 40 | 1 | 34| 2 | 50 | 0 | 35| 2 | 60 | 2 |

投稿2017/11/17 21:02

編集2020/07/26 08:41
AketiJyuuzou

総合スコア1147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

この手の処理はレンジをテーブルに持ったほうがよいです
とくに「2 g 78 」のように70超を60に押し込めようとしているのでしたらなおさらです
一応学生にとって59.5kgと60.0kgは大きな違いなのでweightはdoubleにしておきました

  • 元データ

SQL

1create table weight(weight_range int,weight_min double,weight_max double); 2insert into weight values 3(30,0,39.99), /*30を下回ってもレンジは30*/ 4(40,40,49.99), 5(50,50,59.99), 6(60,60,999.99); /*70を超えてもレンジは60*/ 7 8create table student(class int,name varchar(20),weight double); 9insert into student values 10(1,'a',38), 11(1,'b',52), 12(1,'c',56), 13(1,'d',62), 14(2,'e',45), 15(2,'f',65), 16(2,'g',78); 17

ホントはクラスもテーブルを使うほうがいいのですが、今回はdistinctで処理します

SQL

1select t1.class,t1.weight_range,coalesce(t4.count,0) as count 2from (select class,weight_range from weight 3inner join (select distinct class from student) as sub on 1) as t1 4left join ( 5select class,weight_range,count(*) as count 6from weight as t2 7inner join student as t3 on t3.weight between t2.weight_min and t2.weight_max 8group by class,weight_range 9) as t4 on t1.class=t4.class and t1.weight_range=t4.weight_range 10order by class,weight_range 11

投稿2017/11/15 03:13

yambejp

総合スコア114839

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SVC34

2017/11/15 03:54

> この手の処理はレンジをテーブルに持ったほうがよいです > とくに「2 g 78 」のように70超を60に押し込めようとしているのでしたらなおさらです なるほど、参考になります
shiono

2017/11/16 04:23

回答ありがとうございます レンジテーブルが汎用的でとても参考になりました ベストアンサーにさせていただきます
guest

0

以下は共通表式 (CTE) を用いたPostgreSQLでの例。一時的な表をSQL中に記述することが出来ます。

体重レンジのCTEとクラス一覧のCTEをクロス結合して集計パターンを網羅した中間テーブルを作り、そこにtbl_studentを外部結合して集計しています。

共通表式はMySQLでは8.0からでしか利用できませんが、他の主要なDBMSでは以前からサポートされています。

sql

1WITH cte_w ( 2 weight_range 3) AS ( 4 SELECT 30 UNION ALL 5 SELECT 40 UNION ALL 6 SELECT 50 UNION ALL 7 SELECT 60 8), 9cte_c ( 10 class 11) AS ( 12 SELECT 1 UNION ALL 13 SELECT 2 14) 15SELECT 16 tmp.class 17 ,tmp.weight_range 18 ,COUNT(tbl_student.weight) 19FROM 20 (SELECT * FROM cte_c, cte_w) AS tmp 21 LEFT OUTER JOIN tbl_student 22 ON tmp.class = tbl_student.class 23 AND ( 24 tmp.weight_range = TRUNC(tbl_student.weight, -1) 25 OR ( 26 tmp.weight_range = 60 27 AND tbl_student.weight >= 60 28 ) 29 ) 30GROUP BY 31 tmp.class 32 ,tmp.weight_range 33ORDER BY 34 tmp.class 35 ,tmp.weight_range 36;

投稿2017/11/14 21:32

編集2017/11/14 22:36
SVC34

総合スコア1149

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shiono

2017/11/16 04:20

迅速な回答ありがとうございます 共通表式を初めて知り、大変勉強になりました! 参考にさせていただきます
guest

0

まず、体重を10単位に丸めるには TRUNCATE関数 を使います。(テーブルを削除する TRUNCATE文 とは違うので注意)

MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.6.2 数学関数

sql

1SELECT TRUNCATE(38, -1); 2-> 30

つぎに、レコードが無い体重も0人と取得したい件は

SQLで集約した時系列データの値が0となる行を補完する - Qiita

などSQLで無理矢理実装する方法もありますが、存在しないデータを扱うのはDBのお仕事では無いので、できればアプリ側で作るのがよいと思います。

投稿2017/11/14 14:45

miyahan

総合スコア3095

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shiono

2017/11/16 04:14

迅速な回答ありがとうございます 参考にさせていただきます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問