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

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

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

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

Q&A

3回答

1430閲覧

MySQLのSELECT文のWHEREの指定方法について

Clementine

総合スコア157

MySQL

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

0グッド

0クリップ

投稿2018/06/09 17:27

表題の件につきまして質問致します。

テーブル名:favo
|ID|user_id|value|
|:--|:--:|-:-|
|1|1|リンゴ|
|2|1|バナナ|
|3|2|リンゴ|
|4|2|バナナ|
|5|2|オレンジ|
|6|3|リンゴ|
|7|3|バナナ|
|8|3|オレンジ|
|9|3|パイナップル|

上記テーブルから以下の条件でデータを取得するSELECT文の書き方を教えてください。

1.取得するデータはfavoテーブルのuser_idを2つ取得する
2.取得するuser_idは重複しない
3.リンゴ、バナナ、オレンジ、パイナップルの全てが登録されているuser_idを取得
4.(3.)の条件を満たすデータが無い場合、リンゴ、バナナ、オレンジの3つが登録
されているuser_idを取得する
5.並び順は最も条件を満たしている順である事

※上記条件にて取得するuser_idは、[3,2]の順になります。

以上、宜しくお願い致します。

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

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

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

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

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

guest

回答3

0

要件が不十分なので、とりあえず書いてあることを最低限満たすもの。

sql

1SELECT user_id, group_concat(`value`), count(DISTINCT `value`) FROM favo 2GROUP BY user_id 3HAVING count(`value`) >= 3 4ORDER BY count(DISTINCT `VALUE`) desc

取得するデータはfavoテーブルのuser_idを2つ取得する

例示されたサンプルでは、結果2件のみ抽出されるので、例外は考慮していません。

リンゴ、バナナ、オレンジ、パイナップルの全てが登録されているuser_idを取得

項目がこの4つ以外にあるのかどうか書かれていないので、count(value) で書いた。

(3.)の条件を満たすデータが無い場合、リンゴ、バナナ、オレンジの3つが登録されているuser_idを取得する

項目はマスター化(正規化)すべきかと思う。「パイナップル」を除外すべき理由が不明なので、考慮していない。項目にそれを識別するフィールドがあってしかるべきかと。


他の回答者のため、

sql

1CREATE TABLE `favo` ( 2 `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 3 `user_id` int(11) unsigned NOT NULL, 4 `value` varchar(32) NOT NULL DEFAULT '', 5 PRIMARY KEY (`id`) 6) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

sql

1INSERT INTO `favo` (`id`, `user_id`, `value`) 2VALUES 3 (1,1,'リンゴ'), 4 (2,1,'バナナ'), 5 (3,2,'リンゴ'), 6 (4,2,'バナナ'), 7 (5,2,'オレンジ'), 8 (6,3,'リンゴ'), 9 (7,3,'バナナ'), 10 (8,3,'オレンジ'), 11 (9,3,'パイナップル');

本来、質問者がこうやって情報を提示してくれると回答しやすいんだけどね〜

投稿2018/06/09 19:33

編集2018/06/09 19:39
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Orlofsky

2018/06/10 02:13 編集

ここ何日か正規化に問題があるテーブルでの質問が続きましたね。パフォーマンスは悪いし、複雑なSQLの維持に苦労します。SQLで使われているテーブルはCREATE TABLEが、現行のデータはINSERTが必要って程度の初歩的なスキルもないのも困りものです。 何百テーブルもあるのに正規化を理解できていない人たちだけで設計されたシステムのパフォーマンス・チューニングで呼ばれても、テーブル設計から直さないとパフォーマンスは改善できません、って報告しないといけなかったことが何度もあります。
sazi

2018/06/10 04:23 編集

(低評価はしていません) このSQLだと、要素3つ以上のものの取得です。 例えばパイナップルを含んだ要素3つのものも取得してしまいますので、要素は限定する必要があります。
guest

0

SQLで書くとごちゃごちゃしそうな感じですね。
リンゴ、バナナ、オレンジで絞ったあと、アプリケーション側で処理するのが一番無難ではないでしょうか。
パフォーマンス的にも全部SQLに収めても問い合わせ行数は変わらない気がします。

投稿2018/06/09 18:55

sagami1991

総合スコア216

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

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

sagami1991

2018/06/09 19:58

低評価なのか、悲しい アプリケーション側で処理するのが一番なんだと思うんだけどなあ
m.ts10806

2018/06/09 20:40

(私は低評価押してません) アプリケーション側が一番とは一概には言えませんが、 そもそも要件として何かしらのアプリケーションからの利用かどうか不明だからではないでしょうか。 タグからすると単にMySQLから利用しているだけの可能性も高いですし。そういった意味では「要件不明」(質問内容不十分)ですね。
sazi

2018/06/10 04:19 編集

(低評価は付けていません) >パフォーマンス的にも全部SQLに収めても問い合わせ行数は変わらない気がします。 そうでしょうか? 質問の例では2件に限定されています。それが2/10000のように母数が大きくなればなるほど、かつ並べ替えまでするとなると、パフォーマンスは変わってくると思います。
guest

0

条件をSQLを構成する際に考慮していく順番に並べ替えしました。
先ずは、取得するデータの集合を考え、それらを絞り込んだり結合したり加工するという風に考えると、
混乱せずにすむのではないかと思います。

3.リンゴ、バナナ、オレンジ、パイナップルの全てが登録されているuser_idを取得
4.―1リンゴ、バナナ、オレンジの3つが登録されているuser_idを取得する
4.―2(3.)の条件を満たすデータが無い場合、(4.―1)の条件を満たすuser_idを取得する
2.取得するuser_idは重複しない
1.取得するデータはfavoテーブルのuser_idを2つ取得する
5.並び順は最も条件を満たしている順である事

3と4の集合の完全外部結合より条件を加えます。
(MySQLでは完全外部結合は使えないので、代替え方法を使用)

SQL

1select base.user_id 2from ( 3 select distinct user_id from favo 4 ) base 5 left join ( 6 select user_id, count(distinct value) as value_count 7 from favo 8 where value in('リンゴ','バナナ','オレンジ','パイナップル') 9 group by user_id 10 having count(distinct value)=4 11 ) as count4 12 on base.user_id=count4.user_id 13 left join ( 14 select user_id, count(distinct value) as value_count 15 from favo 16 where value in('リンゴ','バナナ','オレンジ') 17 group by user_id 18 having count(distinct value)=3 19 ) as count3 20 on base.user_id=count3.user_id 21where coalesce(count4.user_id,count3.user_id) is not null 22order by coalesce(count4.value_count,count3.value_count) desc 23 , base.user_id 24limit 2

追記

条件の要素を昇順で指定する前提であれば、group_concat()を使用して簡潔に記述することもできます。
最初のSQLとは基にする集合をどうするかという点が異なります。

SQL

1select * 2from ( 3 select user_id, count(distinct value) as value_count 4 , group_concat(distinct value order by value) as value_list 5 from favo 6 group by user_id 7) agg 8where value_list in ('オレンジ,パイナップル,バナナ,リンゴ','オレンジ,バナナ,リンゴ') 9order by value_count desc, user_id 10limit 2

投稿2018/06/10 01:53

編集2018/06/10 06:37
sazi

総合スコア25188

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問