排除列值的连接记录?

时间:2016-11-29 22:28:48

标签: mysql sql postgresql join

例如,如果我有球和盒子,球可以放在很多盒子里,盒子可以锁定,我怎样才能选择不在锁定盒子里的球?

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

3 个答案:

答案 0 :(得分:2)

我认为你的意思是:选择永远不会被锁在盒子里的球。

如果是这样,我会想到#burger-box > #cpBtn > div { transition-delay: 0.5s; } #burger-box > #cpBtn > div:first-child { transition-delay: 0s; } #burger-box > #cpBtn > div:last-child { transition-delay: 1s; } 查询:

not exists

答案 1 :(得分:0)

执行此操作的最简单方法可能是使用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
)

答案 2 :(得分: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 ) );