menu_code | ingredient_code
-----------+-----------------
100 | abc
101 | efg
102 | hij
100 | xxx
100 | zzz
上記のようなテーブルがあったとします。
この時、 ingredient_code = 'abc' and ingredient_code ='xxx'
の場合はmenu_code == 100がヒットし、
ingredient_code = 'abc' and ingredient_code = 'xxx' and ingredient_code = 'yyy' の場合は、ヒットしないようなSQL文を書きたいのですが、exists演算子を使わないで
書きたいです(というか、副問い合わせはしようしないで(レスポンスが遅くなるので))が、
方法があるのかすらわかりません。
どなたか、教えていただけないでしょうか。
KotoriMaturiさんへ
返答ありがとうございます。
そうです。ingredient_codeの条件が一つでも外れている場合は
ヒットしない、という動作にしたいです。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答6件
0
bool_orを使ってみました :-)
sql
1with t(menu_code,ingredient_code) as( 2values(100,'abc'), 3 (100,'xxx'), 4 (100,'zzz'), 5 (101,'efg'), 6 (102,'hij')) 7select menu_code 8 from t 9group by menu_code 10having bool_or(ingredient_code = 'abc') 11 and bool_or(ingredient_code = 'xxx'); 12 13| menu_code | 14|-----------| 15| 100 | 16
投稿2016/08/13 05:37
総合スコア1147
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
以下のSQLはいかがでしょうか。
同じような記述が続くので好みは分かれると思いますが、できるだけ簡単で確実な方法を考えてみました。
SQL
1select menu_code from table001 where ingredient_code = 'abc' 2intersect 3select menu_code from table001 where ingredient_code = 'xxx' 4intersect 5select menu_code from table001 where ingredient_code = 'zzz' 6;
ちなみに、menu_code列以外も取得する場合は、以下で実現できます。
SQL
1select * from table001 2where menu_code in( 3 select menu_code from table001 where ingredient_code = 'abc' 4 intersect 5 select menu_code from table001 where ingredient_code = 'xxx' 6 intersect 7 select menu_code from table001 where ingredient_code = 'zzz' 8);
追記:
以下の通り、動作確認をしてみました。PostgreSQLのバージョンは9.5.3です。
(長くなってしまい申し訳ございません。)
SQL
1--テスト用テーブル・データ作成 2drop table if exists table001; 3create table table001( 4 menu_code varchar(3), 5 ingredient_code varchar(3), 6 other_key varchar(3), 7 note text, 8 --同一のmenu_code,ingredient_codeの組み合わせが複数行存在する場合も想定 9 primary key(menu_code,ingredient_code,other_key) 10); 11insert into table001 values('100','abc','A','OK'); 12insert into table001 values('100','xxx','B','OK'); 13insert into table001 values('100','zzz','C','OK'); 14insert into table001 values('101','efg','A','NG'); 15insert into table001 values('102','hij','A','NG'); 16insert into table001 values('103','abc','A','NG'); 17insert into table001 values('104','abc','A','NG'); 18insert into table001 values('104','xxx','B','NG'); 19insert into table001 values('105','abc','A','NG'); 20insert into table001 values('105','abc','B','NG'); 21insert into table001 values('105','zzz','C','NG'); 22insert into table001 values('106','abc','A','OK'); 23insert into table001 values('106','xxx','B','OK'); 24insert into table001 values('106','zzz','C','OK'); 25insert into table001 values('106','zzz','D','OK'); 26insert into table001 values('107','abc','A','OK'); 27insert into table001 values('107','xxx','B','OK'); 28insert into table001 values('107','zzz','C','OK'); 29insert into table001 values('107','efg','D','OK'); 30 31--テスト1(menu_codeが1行以上該当する場合) 32select * from table001 33where menu_code in( 34 select menu_code from table001 where ingredient_code = 'abc' 35 intersect 36 select menu_code from table001 where ingredient_code = 'xxx' 37 intersect 38 select menu_code from table001 where ingredient_code = 'zzz' 39); 40 41--結果 42-- menu_code | ingredient_code | other_key | note 43-------------+-----------------+-----------+------ 44-- 100 | abc | A | OK 45-- 100 | xxx | B | OK 46-- 100 | zzz | C | OK 47-- 106 | abc | A | OK 48-- 106 | xxx | B | OK 49-- 106 | zzz | C | OK 50-- 106 | zzz | D | OK 51-- 107 | abc | A | OK 52-- 107 | xxx | B | OK 53-- 107 | zzz | C | OK 54-- 107 | efg | D | OK 55--(11 行) 56 57--テスト2(menu_codeが1行も該当しない場合) 58select * from table001 59where menu_code in( 60 select menu_code from table001 where ingredient_code = 'abc' 61 intersect 62 select menu_code from table001 where ingredient_code = 'xxx' 63 intersect 64 select menu_code from table001 where ingredient_code = 'fff' 65); 66 67--結果 68-- menu_code | ingredient_code | other_key | note 69-------------+-----------------+-----------+------ 70--(0 行)
投稿2016/08/11 15:56
編集2016/08/12 03:09総合スコア37
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
Postgreはよくわからないんですが、普通にSQLで書けば
項目2つ
SQL
1select menu_code 2from tbl where ingredient_code in ('abc','xxx') 3group by menu_code 4having count(distinct ingredient_code)=2;
項目3つ
SQL
1select menu_code 2from tbl where ingredient_code in ('abc','xxx','yyy') 3group by menu_code 4having count(distinct ingredient_code)=3;
としませんか?
項目数を自動で提案したい場合はなんらかの別テーブルを用意するといいでしょう
投稿2016/08/08 00:50
総合スコア117605
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
JOINはサブクエリでは無いと言う事で。。
SQL
1select A.menu_code from table A 2join table B on A.menu_code=B.menu_code and A.ingredient_code='abc' and B.ingredient_code='xxx' 3left join table C on A.menu_code=C.menu_code and A.ingredient_code='abc' and C.ingredient_code='yyy' 4where C.ingredient_code is NULL;
投稿2016/08/07 06:57
総合スコア4070
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
サブクエリが一概にパフォーマンスを悪化させるって訳でもないのですが、
サブクエリを使わないという制約を課すなら以下のような感じでどうでしょう?
もう少し考えてみますが、一応下記で大丈夫です。
レコードが取れない条件を入力された際の対応がどうしても思いつかない・・・
SQL
1SELECT 2 MAX(menu_code) AS menu_code 3FROM 4 TABLE 5WHERE 6 ingredient_code IN ('abc', 'xxx', 'yyy') 7HAVING 8 MAX(menu_code) = MIN(menu_code) 9AND COUNT(*) >= 3 -- 条件の数(※ただし「aaa」が2回など同一条件が複数指定されるとNG)
ただ集約関数使いまくるのとHAVING句を使うからむしろパフォーマンスが悪いかも・・・
・追記
禁を犯してFROM句でサブクエリを用いてみました。
すごく苦しいコード・・・orz
SQL
1SELECT 2 MAX(menu_code) AS menu_code 3FROM 4 ( 5 SELECT 6 'abc' AS cond 7 UNION ALL 8 SELECT 9 'xxx' 10 UNION ALL 11 SELECT 12 'yyy' 13 ) T1 14 LEFT JOIN TABLE T2 15 ON T2.ingredient_code = T1.cond 16HAVING 17 MAX(menu_code) = MIN(menu_code) -- 指摘を受け修正 18AND COUNT(*) = COUNT(menu_code)
###補足
ちなみにFROM句におけるサブクエリを結合する方法を用いると、
WHERE句でのサブクエリ(相関副問い合わせ)と比べ高速に動作する機会は多いと思われます。
投稿2016/08/06 18:30
編集2016/08/08 10:16総合スコア1636
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/08/08 05:51

0
当初投稿したものが間違っていたため再考したのですが、ましなコードは浮かびませんでした。
ごり押し気味な回答になっています。すみません
サブクエリを使わないとなると、こんな感じでしょうか?
(動作確認してません)
SQL
1SELECT menu_code 2FROM table 3GROUP BY menu_code 4HAVING SUM( 5 CASE 6 WHEN ingredient_code = 'abc' OR ingredient_code ='xxx' 7 THEN 1 ELSE 0 8 END 9) >= 2 /* この2は比較条件の数 */
または
SQL
1SELECT menu_code 2FROM table 3GROUP BY menu_code 4HAVING SUM(CASE WHEN ingredient_code = 'abc' THEN 1 ELSE 0 END) = 1 5AND SUM(CASE WHEN ingredient_code = 'xxx' THEN 1 ELSE 0 END) = 1 6
テーブル設計やデータ件数とその偏りに大きく影響を受けると思うので、サブクエリ利用より常に早いか?と問われると怪しいです(むしろサブクエリ利用のほうが早いケースが多いかも)
投稿2016/08/06 18:18
編集2016/08/07 04:33総合スコア2068
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/08/06 20:06

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。