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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

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

Q&A

解決済

3回答

6275閲覧

MySQLのCOUNTを使って件数0のデータを含めたデータを表示させるSELECT文について

reprepstu

総合スコア8

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

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

0グッド

0クリップ

投稿2018/12/12 13:12

お世話になります。Mysql(バージョン5.7.23)あるSQL文を勉強しております。
以下のようなテーブルとデータを用意しました。

CREATE TABLE main_table ( `mainID` int(11) NOT NULL, `name` varchar(50) NOT NULL, PRIMARY KEY (`mainID`) ); CREATE TABLE sub_table ( `subID` int(11) NOT NULL, `main1` int(11) NOT NULL, `main2` int(11) NOT NULL DEFAULT 0, `main3` int(11) NOT NULL DEFAULT 0, PRIMARY KEY (`subID`) )

main_table(mainIDは1から始まります)

mainIDname
1name1
2name2
3name3
4name4
5name5
6name6
7name7
8name8

sub_table(subIDは1から始まります)

subIDmain1main2main3
1120
2214
3456
4312
5810

このとき各mainIDに対してmain1またはmain2またはmain3に登録されているデータのSELECT文を考えています。
例えば、mainIDが8まで、subIDが5まで登録されていたら以下のように出力されるSELECT文を考えています。

mainIDname件数
1name14(subID=1のmain1、subID=2のmain2、subID=4のmain2、subID=5のmain2の計4件)
2name23(subID=1のmain2、subID=2のmain1、subID=4のmain3の計3件)
3name31(subID=4のmain1の1件)
4name42(subID=2のmain3、subID=3のmain1の計2件)
5name51(subID=3のmain2の1件)
6name61(subID=3のmain3の1件)
7name70(データないので0件)
8name81(subID=5のmain1の1件)

私が考えたSQL文は以下の内容ですが、もっと簡単な文にできるかどうか教えてください。
よろしくお願いします。

SELECT `mainID` , name , IFNULL(M1.c1,0) + IFNULL(M2.c2,0) + IFNULL(M3.c3,0) 件数 FROM mysql.main_table LEFT JOIN (SELECT main1, COUNT(main1) c1 FROM sub_table GROUP BY main1) M1 ON M1.main1 = mainID LEFT JOIN (SELECT main2, COUNT(main2) c2 FROM sub_table GROUP BY main2) M2 ON M2.main2 = mainID LEFT JOIN (SELECT main3, COUNT(main3) c3 FROM sub_table GROUP BY main3) M3 ON M3.main3 = mainID ORDER BY `mainID`

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

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

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

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

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

guest

回答3

0

ベストアンサー

例えば

SQL

1select mainID,name,coalesce(cnt,0) as cnt from main_table as t1 2left join ( 3select main,sum(cnt) as cnt from ( 4select main1 as main,count(*) as cnt from sub_table group by main 5union all select main2 as main,count(*) from sub_table group by main 6union all select main3 as main,count(*) from sub_table group by main 7) as t3 group by main 8) as t2 on t1.mainID=t2.main 9

しかしこれでは非効率なので

SQL

1CREATE TABLE sub2 ( 2 `subID` int(11) NOT NULL, 3 `main` int(11) NOT NULL, 4 `sort` int(11) NOT NULL, 5 unique (`subID`,`sort`) 6); 7 8insert into sub2 values 9(1,1,1), 10(1,2,2), 11(1,0,3), 12(2,2,1), 13(2,1,2), 14(2,4,3), 15(3,4,1), 16(3,5,2), 17(3,6,3), 18(4,3,1), 19(4,1,2), 20(4,2,3), 21(5,8,1), 22(5,1,2), 23(5,0,3);

として

SQL

1select mainID,name,coalesce(cnt,0) as cnt from main_table as t1 2left join ( 3select main,count(*) as cnt from sub2 group by main 4) as t2 on t1.mainID=t2.main

とするとよい
ちなみに、sub2からsub_tableのような表示にするには

SQL

1select subID 2,sum((sort=1)*main) as main1 3,sum((sort=2)*main) as main2 4,sum((sort=3)*main) as main3 5from sub2 6group by subID

投稿2018/12/13 01:04

yambejp

総合スコア114839

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

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

reprepstu

2018/12/15 02:22

テーブルの構成まで考えていただき、ありがとうございます。 教えていただいた内容を実行したら、思い通りの結果になりました。
guest

0

sub_tableを
subID int(11) NOT NULL,
mainID int(11) NOT NULL,
main1とかmain2とかの情報 int(11) NOT NULL
の構成にしたほうがいいとおもいます

投稿2018/12/12 13:19

takg

総合スコア125

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

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

reprepstu

2018/12/15 01:58

すみません、自宅で適当にtableを作成したので、他の人が見たら不自然なカラムになっていると思います。 よろしければ、提案して頂いたtableの構成にしたほうが良いと思った理由を教えていただけますか?
takg

2018/12/15 05:08

提示なさっている構成は、今回のご質問のようにクエリが書きにくかったり、あとは拡張性が低かったりといったデメリットがあると思います。 もちろんreprepstuさんの要件に依るので、一概には言えませんが。 行持ち、列持ちで検索するとよいと思います。 参考: http://gihyo.jp/dev/serial/01/sql_academy2/000302
reprepjqu

2018/12/24 11:48

連絡が遅くなり申し訳ありません。 教えていただきありがとうございます。
guest

0

結合の演算子は=ばかりじゃないのです。

SQL

1SELECT mainID, `name`, count(distinct subID) 2FROM main_table m LEFT JOIN sub_table s 3 on m.mainID in (s.main1, s.main2, s.main3) 4GROUP BY mainID, `name` 5ORDER BY mainID

投稿2018/12/12 15:13

編集2018/12/12 15:14
sazi

総合スコア25195

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

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

yambejp

2018/12/13 00:51

質問の趣旨から言って満たしているとは思いますけど この場合subIDごとにmain1,main2,main3がユニークであるという条件が必要です。
sazi

2018/12/13 00:58

ユニークでない場合にsubIDを別々にカウントするというのが要件でなければ、ユニークでなくともsubidは重複して取得されるわけではないですし、さらにcount()でdistinctしているので問題無いと思うのですが。
sazi

2018/12/13 01:08 編集

ああ、ユニークでない場合は、元のSQLと違う結果になりますね。 でも、カウントの意図としては別にカウントされちゃうのは意図するところではないと思いますけどね。
reprepstu

2018/12/15 02:09

=だけで結合しようとばかり考えていました。 教えていただき、ありがとうございます。 因みに、subIDごとにmain1,main2,main3がユニークでないのを想定でした。情報が不足して申し訳ございません。 教えて頂いたSQLを実行しましたら、自分が考えたものと同じ結果になりました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問