2016-11-29 12 views
2

たとえば、ボールとボックスがある場合、ボールは多くのボックスにあり、ボックスはロックできます。ロックされたボックスにないボールはどのように選択できますか?私はこの使用して左を作ってみた列値の結合レコードを除外しますか?

balls 
    id name 
    == ==== 
    1 in neither 
    2 in unlocked 
    3 in locked 
    4 in both 

boxes 
    id locked 
    == ====== 
    1 0 
    2 1 

boxings 
    ball_id box_id 
    ======= ====== 
    2  1 
    3  2 
    4  1 
    4  2 

が参加し、それは私が除外するボール 「の両方に」を返します。

SELECT balls.* 
FROM balls 
LEFT OUTER JOIN boxings ON boxings.ball_id = balls.id 
LEFT OUTER JOIN boxes ON boxes.id = boxings.box_id 
WHERE (boxings.box_id IS NULL or boxes.locked = 0) 
    AND boxes.id NOT IN (
    SELECT id FROM boxes WHERE locked = 1 
    ) 

望ましい結果:

id name 
== ==== 
1 in neither 
2 in unlocked 

SQLフィドル: http://sqlfiddle.com/#!9/c26ab/4

答えて

2

私はあなたが意味すると仮定します。ロックされたボックスになることはありませんボールを選択してください。

もしそうなら、not existsクエリが頭に浮かぶ:

select b.* 
from balls b 
where not exists (select 1 
        from boxings bxb join 
         boxes bo 
         on bxb.box_id = bo.id 
        where bxb.ball_id = b.id and bo.locked = 1 
       ); 
+0

それだ、ありがとう:とにかく

は、ここで抗参加アプローチの異なるバリエーションです! – jemminger

0

これを行うには、最もstraightforwad方法はNOT EXISTSで、おそらくです:

select id, name 
from balls 
where not exists (
    select NULL 
    from boxings 
    inner join boxes on boxes.id = boxings.box_id 
    where boxes.locked = 1 
    and boxings.ball_id = balls.id 
) 
0

私はそれが面白いの両方の答えがすでに両方掲載することを見つけますジョイン基準のいくつかを「」の句に入れるというやや奇妙なアプローチをとります:

inner join boxes on boxes.id = boxings.box_id 
where boxes.locked = 1 

もっとも奇妙なのは、確かにthe same people advise elsewhere to not put join conditions in WHERE clausesです。

SELECT * 
    FROM balls 
WHERE id NOT IN (SELECT ball_id 
        FROM boxings 
          NATURAL JOIN 
          (SELECT id AS box_id FROM boxes WHERE locked = 1) 
          NATURAL JOIN 
          (SELECT id AS ball_id FROM boxings)); 
関連する問題