2017-10-27 4 views
0

次のSQLクエリは、label_itemsに指定された名前を持つlabel_item_listsを見つけることを目的としています。2つのEXISTSステートメントが期待どおりに動作しないSQLクエリー

SELECT lils.id FROM label_item_lists AS lils 
    INNER JOIN label_items AS items ON lils.id = items.label_item_list_id 
    WHERE EXISTS(SELECT * FROM label_item_lists WHERE items.name=?) 
    OR EXISTS(SELECT * FROM label_item_lists WHERE items.name=?) 

label_item_listsのIDを正しく返します。いずれかの名前の項目を持つリスト。ただし、ORではなくAND演算子を使用した同じクエリは結果を返しません。

明らかに、両方の名前に一致するlabel_itemsを持つlabel_item_listエントリがあります。実際、OR SQLクエリはこれらのエントリに対してIDを2回返しますが、ANDクエリは結果を返しません。このような理由から、EXISTSでこれらのJOINされたクエリがどのように機能するかに関する重要な情報が不足している可能性があります。助けてくれてありがとう!

---------------------------------------------------------------- 
| label_items  | id  | name  | label_item_list_id | 
---------------------------------------------------------------- 
| Row1    | 1   | foo  | 1     | 
---------------------------------------------------------------- 
| Row2    | 2   | bar  | 1     | 
---------------------------------------------------------------- 
| Row3    | 3   | bar  | 2     | 
---------------------------------------------------------------- 


-------------------------------- 
| label_item_lists | id  | 
-------------------------------- 
| Row1    | 1   | 
-------------------------------- 
| Row2    | 2   | 
-------------------------------- 

私はそれだけで私は、「foo」と「bar」を探しています二つの名前のいずれかを持っているように、第1 label_item_listではなく、秒を返すようにしたいです。

+0

サンプルデータと希望の出力をフォーマットされたテキスト(イメージではなく)で共有する – zarruq

+0

投稿を編集してデータを追加しました。私はこれがあなたが探していたものだと願っています! –

+1

'items.name =? 'と推測できませんので、完全な質問をしてください。 – Susang

答えて

0

WHERE EXISTS(SELECT * FROM label_item_lists WHERE items.name=?) 
AND EXISTS(SELECT * FROM label_item_lists WHERE items.name=?) 

からのお問い合わせには

WHERE EXISTS(SELECT * FROM label_item_lists lst WHERE lst.name=?) 
AND EXISTS(SELECT * FROM label_item_lists lst WHERE lst.name=?) 
+0

あなたの返事をありがとうが、私はこれが私のために働くのか分からない。 2つ目のクエリがlabel_item_listsの名前の列にアクセスする以外は同じですが、残念ながらlabel_item_listsには名前の列はありません。name列はlabel_itemsに属し、外部キーを介してlabel_item_listsテーブルに関連付けられています。 –

0

にWHERE条件を変更してみて、同じ出力行にそれがあるので、決して起こらないだろう両方のフィルタが適用されますので、何も返さないだろう空白の出力を与えます。 And Or演算子は、最初の条件がfalseになるまで、OR演算子の後で条件をチェックしません。

はこのような何かを試してみてください、@は、2回の検索を区別するだけのプレースホルダです:

select * from label_items lil 
where label_item_list_id 
in (
select li.label_item_list_id from 
label_items li 
inner join label_items l1 
on li.label_item_list_id = l1.label_item_list_id 
and li.name <> l1.name 
where concat(li.name,'@',l1.name) = '[email protected]') 
+0

あなたの提案をありがとう!微調整だけで、私の目的のためにうまくいった!しかし、私は多くの名前を付けることがあります。たとえば、8つの異なるlabel_itemに一致するlabel_item_listを見つけることができます。申し訳ありませんが、私はこれを指定しませんでした。内部結合を追加し続けることはできますか?それは5または6テーブルで面倒なパフォーマンスの損失ですか? –

0

これは私が最終的に思い付いたものです!私は100%自信を持っているわけではありませんが、それまではうまくいっています。私はRubyとActiveRecordに少しだけ機能を追加して、必要なだけ一致させ、正確に一致するものだけを返すようにしました(リストに余分な名前はありません)。

items = ["foo", "bar"] 
    db = ActiveRecord::Base.connection 

    query = <<-EOS 
    SELECT lils.id FROM label_item_lists AS lils 
    JOIN label_items AS items ON items.label_item_list_id = lils.id 
    WHERE lils.id IN (
     SELECT label_item_list_id FROM label_items AS items 
     WHERE items.name IN (#{(['?'] * items.length).join(',')}) 
    ) AND lils.id NOT IN (
     SELECT label_item_list_id FROM label_items AS items 
     WHERE items.name NOT IN (#{(['?'] * items.length).join(',')}) 
    ) 
    GROUP BY lils.id 
    HAVING COUNT(DISTINCT items.name) = #{items.length} 
    EOS 

    query = ActiveRecord::Base.send(:sanitize_sql_array, [query, *(items*2)]) 

基本的には名前が与えられた名前のリスト指定された名前(items配列)のリストと、それはまた名前が外部(またはNOT IN)されていないことを確認の両方であることを確認します。一致しない名前を持つlabel_itemsのリストは、後者のINクエリによって除外されます。これは、 "foo"と "bar"の両方を含むlabel_item_listが "lorem"に含まれないようにするために役立ちます。

関連する問題