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

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

ただいまの
回答率

90.53%

  • MySQL

    6829questions

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

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

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 484

ssk

score 273

説明

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

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

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

<input type="checkbox" name="holiday[]" value="1" checked="checked">月曜日
<input type="checkbox" name="holiday[]" value="2">火曜日
<input type="checkbox" name="holiday[]" value="3">水曜日
<input type="checkbox" name="holiday[]" value="4">木曜日
.
.
.
CREATE TABLE `shop` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT );
CREATE TABLE `shop_holiday` ( `shop_id` INTEGER, `holiday` INTEGER );
CREATE TABLE `week` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` INTEGER );
//前回、Kosuke_Shibuya様より助言いただいたSQL文
select 
    S.name as shop_name
    , group_concat(W.name) as holidays
from 
    shop S
left join shop_holiday SH 
    on S.id = SH.shop_id
left join week W 
    on SH.holiday = W.id
where 
    W.id = '0'
group by 
    S.id
shop
id name
1 山田商店
2 スーパータナカ 
3 青木ストア
shop_holiday
shop_id holiday
1 1
1 2
2 1
2 2
2 3
3 1
3 4
holiday
id name
1 月曜日
2 火曜日
3 水曜日
4 木曜日
5 金曜日
6 土曜日
7 日曜日
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

こうですね

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/22 14:53

    ありがとうございます。
    having count(*)=2という手法を初めて知りました。

    色々と試してみることにします。

    キャンセル

  • 2017/02/22 14:58

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

    キャンセル

  • 2017/02/22 14:58

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

    キャンセル

  • 2017/02/22 15:01

    なんと

    キャンセル

  • 2017/02/22 15:06

    あ、ほんとだ。月曜日or火曜日という命題でしたね
    誤解していました

    ・月曜か火曜の最低でもどちらかなら「having count(*)>=1」
    ・月曜か火曜かどちらかがなら「having count(*)=1」
    ですね

    キャンセル

  • 2017/02/22 15:10

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

    キャンセル

  • 2017/02/22 16:01

    having count(*)=1で取得することができました。

    助言、ありがとうございます。
    データベース設計は難しいですね。。

    キャンセル

0

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

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


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

SELECT s.id, s.name, h.name
FROM shop s
...


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

もう少しひねって、

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


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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/22 13:30

    ありがとうございます。

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

    キャンセル

  • 2017/02/22 14:55

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

    キャンセル

0

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

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

select 
    S.name as shop_name
    , group_concat(W.name) as holidays
from 
    shop S
left join shop_holiday SH 
    on S.id = SH.shop_id
left join week W 
    on SH.holiday = W.id
where 
    W.id = '0'
AND S.id IN (
    SELECT shop_id FROM shop_holiday 
    WHERE holiday IN (1, 2)
    GROUP BY shop_id having count(shop_id) = 1
)
group by 
    S.id

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

余談ですが...

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/22 14:54

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

    キャンセル

  • 2017/02/22 16: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 16:14

    追記をご確認ください。

    キャンセル

  • 2017/02/22 18:22

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

    キャンセル

同じタグがついた質問を見る

  • MySQL

    6829questions

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