表題の件につきまして質問致します。
テーブル名: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ページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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
0
SQLで書くとごちゃごちゃしそうな感じですね。
リンゴ、バナナ、オレンジで絞ったあと、アプリケーション側で処理するのが一番無難ではないでしょうか。
パフォーマンス的にも全部SQLに収めても問い合わせ行数は変わらない気がします。
投稿2018/06/09 18:55
総合スコア216
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/06/09 20:40
2018/06/10 04:19 編集
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総合スコア25195
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/06/10 02:13 編集
2018/06/10 04:23 編集