質問
「りんご2個以上」かつ「バナナ2個以上」を持っているユーザIDを取得したいです。
以下データの場合、結果としてuser_id=2が得られることを期待していますが思ったような結果が得られません。
(期待する結果を得られるSQLは完成しましたが効率が悪いように思います。改善点や最適な方法が知りたいです。)
テーブル定義
itemsはユーザーの所持品を保存するテーブル
sql
1CREATE TABLE `items` ( 2 `user_id` INT(11) UNSIGNED NOT NULL, 3 `name` VARCHAR(16) NOT NULL COLLATE 'utf8_general_ci', 4 `num` INT(11) UNSIGNED NOT NULL, 5 INDEX `name` (`name`) USING BTREE 6) 7COLLATE='utf8_general_ci' 8ENGINE=InnoDB 9; 10
テーブルデータ
user_id | name | num |
---|---|---|
1 | りんご | 1 |
1 | バナナ | 2 |
2 | りんご | 2 |
2 | バナナ | 2 |
試したこと
以下SQL001は結果が0件です。
りんごが2個以上のwhere条件で既に結果にバナナが含まれていない為、2つめのバナナに関するwhere条件を満たせず0件になったと思われます。
sql
1/* SQL001 */ 2select 3 i.user_id 4from items i 5where 6 (i.name = 'りんご' and i.num >= 2) and 7 (i.name = 'バナナ' and i.num >= 2) 8
そこで、以下SQL002のようにgroup byを利用してnameごとに条件指定ができるようにしたつもりですが結果が0件でした。
sql
1/* SQL002 */ 2select 3 i.user_id 4from items i 5where 6 (i.name = 'りんご' and i.num >= 2) and 7 (i.name = 'バナナ' and i.num >= 2) 8group by 9 i.name
以下SQL003のようにサブクエリで指定すると期待する結果が得られました。
しかし、selectが2回あるのであまり効率が良いSQLとは思えないです。
りんご、バナナの他に検索対象の数が増えた場合、増えた数に比例してサブクエリを増やす必要があるはずです。
sql
1/* SQL003 */ 2select 3 i.user_id 4from items i 5where 6 (i.name = 'りんご' and i.num >= 2) and 7 i.user_id in (select user_id from items where (name = 'バナナ' and num >= 2))
今回のようなケースではどのようなSQLが最適でしょうか?
※追記
以下SQL004でも期待する結果が取れて少しSQLが綺麗になったかと思いましたがりんごが1個、バナナが3個(またはそれ以外の合計が4個以上のパターン)でも結果が0件にならないのでダメでした。
/* SQL004 */ select i.user_id from items i where (i.name = 'りんご') or (i.name = 'バナナ') group by i.user_id having sum(i.num) >= 4
環境
- MariaDB 10.5.9
回答5件
あなたの回答
tips
プレビュー