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

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

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

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

Q&A

解決済

3回答

1697閲覧

MySQLで他テーブルをjoinする検索方法について

ssk

総合スコア332

MySQL

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

0グッド

1クリップ

投稿2017/02/22 04:17

######説明
前々回の質問前回の質問を受けて検索を実装しています。
例えば、チェックボックスの選択を月曜日と火曜日にした場合

[x] 月曜日
[x] 火曜日
[ ] 水曜日
[ ] 木曜日
[ ] 金曜日
[ ] 土曜日
[ ] 日曜日

月曜日or火曜日が定休日のショップをSELECTして一覧に表示したいのですが
どのようにSQL文を書いたらよいでしょうか?

HTML

1<input type="checkbox" name="holiday[]" value="1" checked="checked">月曜日 2<input type="checkbox" name="holiday[]" value="2">火曜日 3<input type="checkbox" name="holiday[]" value="3">水曜日 4<input type="checkbox" name="holiday[]" value="4">木曜日 5. 6. 7.

SQL

1CREATE TABLE `shop` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT ); 2CREATE TABLE `shop_holiday` ( `shop_id` INTEGER, `holiday` INTEGER ); 3CREATE TABLE `week` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` INTEGER );

SQL

1//前回、Kosuke_Shibuya様より助言いただいたSQL文 2select 3 S.name as shop_name 4 , group_concat(W.name) as holidays 5from 6 shop S 7left join shop_holiday SH 8 on S.id = SH.shop_id 9left join week W 10 on SH.holiday = W.id 11where 12 W.id = '0' 13group by 14 S.id

######shop

idname
1山田商店
2スーパータナカ
3青木ストア

######shop_holiday

shop_idholiday
11
12
21
22
23
31
34

######holiday

idname
1月曜日
2火曜日
3水曜日
4木曜日
5金曜日
6土曜日
7日曜日

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

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

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

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

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

guest

回答3

0

ベストアンサー

こうですね

SQL

1select * from shop where id in( 2select shop_id from shop_holiday where holiday in(1,2) group by shop_id having count(*)=2 3)

投稿2017/02/22 04:50

yambejp

総合スコア114572

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

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

ssk

2017/02/22 05:53

ありがとうございます。 having count(*)=2という手法を初めて知りました。 色々と試してみることにします。
退会済みユーザー

退会済みユーザー

2017/02/22 05:58

「月曜日or火曜日」と書いてあるのに、こちらが意図した動きなんですね。
KiyoshiMotoki

2017/02/22 05:58

これだと > 月曜日or火曜日が定休日のショップ ではなく、 「月曜日 AND 火曜日が定休日のショップ」 だけがヒットすることになりますよ。
yambejp

2017/02/22 06:06

あ、ほんとだ。月曜日or火曜日という命題でしたね 誤解していました ・月曜か火曜の最低でもどちらかなら「having count(*)>=1」 ・月曜か火曜かどちらかがなら「having count(*)=1」 ですね
yambejp

2017/02/22 06:10

ちなみに、今回のような正規化は必ずしも効率的なデータの持ち方とは言えません。 選択肢が不特定多数、例えば趣味はなんですか?とか選択肢が増えていくようなものであれば的確なデータの持ち方ですが、言っても曜日は7つしかなくほぼ普遍的なものなので月曜~日曜のカラムを作ったほうが高速で効率的にできるかもしれません
ssk

2017/02/22 07:01

having count(*)=1で取得することができました。 助言、ありがとうございます。 データベース設計は難しいですね。。
guest

0

sql

1SELECT name FROM shop 2WHERE id IN ( 3 SELECT shop_id FROM shop_holiday WHERE holiday IN (1, 2) 4)

#質問に提示されたSQLを基にしたサンプル

sql

1select 2 S.name as shop_name 3 , group_concat(W.name) as holidays 4from 5 shop S 6left join shop_holiday SH 7 on S.id = SH.shop_id 8left join week W 9 on SH.holiday = W.id 10where 11 W.id = '0' 12AND S.id IN ( 13 SELECT shop_id FROM shop_holiday 14 WHERE holiday IN (1, 2) 15 GROUP BY shop_id having count(shop_id) = 1 16) 17group by 18 S.id

ただし、この場合、定休日が「月曜と火曜がともに休日」のものはヒットしないが、
「月曜と水曜(火曜以外)が休日」の場合はヒットする。極端な例だけど、「月曜、水曜、木曜、金曜、土曜、日曜すべて休日で営業日は火曜だけ」というものもヒットする。
「月曜のみ休日のショップ」を検索したい場合は、他の検索方法が必要。yambejpさんのSQLも同様。

#余談ですが...

「○曜日が休日の店舗」を検索するというオペレーションは、一体なんのために実装する必要があるのか。。。
通常、「月曜日に営業している店舗」を検索したいというのが普通。

休日の店舗を検索なんて、空き巣狙いの窃盗団くらいしか役に立たないと思いますが。

投稿2017/02/22 04:27

編集2017/02/22 18:44
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

ssk

2017/02/22 05:54

引き続き、ありがとうございます。 こちらの方法でどのような動きをするか試してみます。
ssk

2017/02/22 07:03

yambejp様へのご指摘まで、ありがとうございます。 left join shop_holiday SH on S.id = SH.shop_id left join week W on SH.holiday = W.id と組み合わせることでセレクトすることができました。 ただ、2行セレクトしているため、一覧で表示する際は1行で表示するようにしてみます。
退会済みユーザー

退会済みユーザー

2017/02/22 07:14

追記をご確認ください。
ssk

2017/02/22 09:22

追記ありがとうございます。 1行1行考えながら、実行してみます。
guest

0

あえて holiday まで使うとして、

SQL

1SELECT DISTINCT s.id, s.name 2FROM shop s 3 INNER JOIN shop_holiday sh ON (sh.id = s.id) 4 INNER JOIN holiday h ON (h.id = sh.holiday) 5WHERE h.name in ('月曜日', '火曜日')

ですかね。
ただこれだと月曜日と火曜日のどちらが(あるいはどちらも)休みなのかまでは出していません。
それまで出すなら

SQL

1SELECT s.id, s.name, h.name 2FROM shop s 3...

となりますね。(同じショップが月曜日と火曜日で2行出ます)

もう少しひねって、

SQL

1SELECT s.id, s.name, 2 CASE SUM(h.id) WHEN 1 THEN '月曜日' 3 WHEN 2 THEN '火曜日' 4 WHEN 3 THEN '月・火' END AS holidays 5FROM shop s 6 INNER JOIN shop_holiday sh ON (sh.id = s.id) 7 INNER JOIN holiday h ON (h.id = sh.holiday) 8WHERE h.name in ('月曜日', '火曜日') 9GROUP BY s.id, s.name

もあるけど、トリッキーすぎるかな。

投稿2017/02/22 04:25

編集2017/02/22 05:25
tacsheaven

総合スコア13703

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

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

ssk

2017/02/22 04:30

ありがとうございます。 >>>同じショップが月曜日と火曜日で2行出ます 一覧で表示する際に同じショップが2行出てしまうと困るので 1行のみセレクトしたいのですが、どのように記述したらよいでしょうか?
ssk

2017/02/22 05:55

ありがとうございます。 上記お2人と組み合わせて、実装いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問