2016-11-29 78 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

我覺得很有意思,這兩個答案已經發布兩採用與WHERE子句中的某些加入條件相同的稍微奇怪的方法:

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));