2016-04-06 10 views
0

テーブルから特定の条件を満たす場合は、DISTINCT IDを返すようにしています。いくつかの基準に基づいて異なるIDを返します

  1. IDは、IDがここにテーブルがあります38または46または67

のCIDを含めることはできません1,26,33,49のCID(すべて)

  • が含まれている必要があります。

    SELECT DISTINCT(c1.id) FROM cte c1 
    LEFT JOIN cte c2 
    ON c1.id = c2.ID 
    AND c2.CID = 38 
    where c2.id IS null 
    

    これだけ作品、私が提示すべきではない、単一のIDを指定した場合:ここで

    enter image description here

    は、私がこれまで持っているものです。私は

    AND c2.CID IN (38,46,67) 
    

    でこれ

    AND c2.CID = 38 
    

    を交換する場合、これは私に正しいIDを返しません。また、c1.CIDにIDを含めるための条件を追加すると、1,26,33,49も不正なIDが返されます。

    この例の表に基づいて、私は戻ってID 12345を取得する必要があります。

    は、ここで私はsubqueryを使用せずに、この出力を取得しようとしているSQLFIDDLE.

    です。

    提案がありますか?

  • +0

    このクエリが機能しない理由は分かりません:「あなたのテーブルから別のIDを選択してください(1,26,33,49)」 – FLICKER

    +0

    これは動作しません。 'ID'は異なる' CIDs 'を持つ複数の行を持つことができます。 1つのselectだけを実行すると、行が除外されますが、IDは除外されません。 – smr5

    +0

    @burzum 'criteria'は複数形であり、単数形は 'criterion'なので、 'criterias'は単語ではありません。 –

    答えて

    3

    SQL Fiddle

    条件付き集約を使用してください。

    SELECT id 
    FROM cte 
    group by id 
    having sum(case when cid in (1,26,33,49) then 1 else 0 end) = 4 
    and sum(case when cid in (38,46,67) then -1 else 0 end) = 0 
    
    +0

    ありがとうございます。あなたのソリューションは私のために働く。ここで 'sum 'が何をしているのか説明できますか?私はその事件を理解しており、すべてのIDが存在しなければならないことを表す '4'がありますが、私は 'sum'の目的を理解していません。 – smr5

    +0

    これらの値を含む行に1を割り当て、各IDごとに合計し、4であるかどうかをチェックします。除外すべきcidの場合、同じことをしますが、3つのcidを持つ行に-1を割り当ててから合計を行います。これらのcidのいずれかが指定されたidに対して存在する場合、合計は0にならず、条件は失敗し、それらのidは返されません。 –

    +0

    ご説明ありがとうございます。 – smr5

    0

    なぜあなたはそのようなことをしなかったのですか?

    AND c2.CID = 38 OR c2.CID = 46 OR c2.CID = 67 
    

    または

    AND c2.CID Like (38,46,67) 
    
    1

    私は作業クエリを作成しますが、非常に奇妙な:)

    -- An ID must contain CID of 1,26,33,49 (all) 
    -- An ID should NOT contain CID of 38 or 46 or 67 
    SELECT valid.ID 
    FROM (
        SELECT ID, CID 
        FROM CTE 
        WHERE CID IN (1,26,33,49) 
        GROUP BY ID, CID 
    ) AS valid 
    WHERE valid.ID NOT IN (
        SELECT ID FROM CTE WHERE CID IN (38,46,67) GROUP BY ID, CID 
    ) 
    GROUP BY valid.ID 
    HAVING COUNT(valid.CID) = 4 
    

    の作業sqlfiddleに見えてきた:http://sqlfiddle.com/#!6/9c862/41

    P.S.を'4'は必須のIDの数です。パラメータの数を変更する場合は、HAVING COUNT句をそれに応じて更新する必要があります。

    +0

    @pavel_morshenyuk私は次のように編集することをお勧めします:HAVING COUNT(DISTINCT valid.CID)= 4指定されたCIDに対して可能な複数のエントリを考慮する必要があります。 –

    +0

    @ ricardo-c提案に感謝します!恐らくそれは意味をなさない。 –

    1

    EXCEPTは、UNIONの反対側にあります。

    SELECT c1.id 
    FROM cte c1 
    WHERE c1.CID IN(1,26,33,49) 
    GROUP BY c1.id 
    HAVING COUNT(DISTINCT c1.CID) = 4 
    
    EXCEPT 
    
    SELECT DISTINCT c1.id 
    FROM cte c1 
    WHERE c1.CID IN(38,46,67) 
    
    +0

    他の例は重複したエントリを考慮しない。 ID 12345とCID 26の4つの重複レコード26 –

    +0

    Strange。 SQLFIDDLEで動作しますが、テーブルに対して同じクエリを実行すると結果が返されません。 – smr5

    +0

    @burzum umあなたのテーブルが異なるかもしれませんが、sqlfiddleから両方の部分をコピーしてみてください。 'スキーマの構築'と 'sqlの実行'を行い、SSMSでテストします。 –

    1

    一時テーブルを使用したい場合は、これが機能します。そして、ここでSQLフィドルです:同じ考えでも同じCIDの複数たオプションを持っていた場合 http://sqlfiddle.com/#!6/9c862/39/0

    Select 
        C.ID 
    ,C.CID 
    ,Case C.CID 
        When 1 then 'Y' 
        When 26 then 'Y' 
        When 33 then 'Y' 
        When 49 then 'Y' 
        Else 'N' 
        End as "Keep" 
    ,Case C.CID 
        When 38 then 'Y' 
        When 46 then 'Y' 
        When 67 then 'Y' 
        Else 'N' 
        End as "Remove" 
    
    Into #Temp 
    
    From CTE as C 
    
    
    
    Select Distinct 
        T.ID 
    
    From #Temp as T 
    
    Group by T.ID 
    
    Having 
        Sum(Case When T.Keep = 'Y' Then 1 Else 0 End) = 4 
        and 
        Sum(Case When T.Remove = 'Y' then 1 Else 0 End) = 0 
    

    は、最初に私が考慮されていませんでした。この場合、最初のselect文にdistinctを追加して、これを動作させることができるはずです。

    +0

    努力のために「1」プラス! – smr5

    +0

    同じコンセプトだけど、tempテーブルがない@vkpはそこではうまくいきました。私はtempテーブルを手に入れてからhaving句を使うまでは考えていませんでした。閉じる –

    関連する問題