右连接没有交叉和另一个条件

时间:2017-03-02 11:11:30

标签: sql join

我想像这样做一个正确的联接:

enter image description here

我希望所有B都没有任何A. 要么 所有B 只是 A.type<> 0(如果他们有一个A.type = 0我不想要他们)

现在我有了这个:

SELECT B.* 
FROM A 
RIGHT JOIN B ON A.ticket = B.id 
WHERE A.id IS NULL
  AND B.state NOT IN (3,4,10)
  AND B.disable = 0

4 个答案:

答案 0 :(得分:2)

没有理由使用RIGHT JOIN。对于大多数人来说,由于两个原因,它比LEFT JOIN更令人困惑。首先,读取FROM子句"从左到右"。 LEFT JOIN保留子句中第一个表中的所有行。尚未见过的最后一张表中的RIGHT JOIN。其次,FROM子句从左到右解析,这在组合多个外连接时引入了一些微妙的问题。

接下来,您明确说:

  

我想排除没有A.Type = 0

的B.

这相当于:

  

我想要包含没有A.Type = 0的B

这不是一个外部联接。我认为这更接近你想要的东西:

在你的情况下:

SELECT  B.*
FROM B
WHERE NOT EXISTS (SELECT 1
                  FROM A
                  WHERE A.ticket = B.id AND A.Type = 0
                 ) AND
      B.state NOT IN (3, 4, 10) AND B.disable = 0;

答案 1 :(得分:0)

你想要B,如果A中有任何值,那么它的类型是<> 0,所以:

SELECT * FROM B
WHERE B.id NOT IN (
   SELECT ticket  FORM A
   WHERE A.type = 0 )

不可接受

可能你想要这样的东西:

SELECT  B.* FROM A 
RIGHT JOIN B
ON A.ticket = B.id 
WHERE
     A.type<>0
 -- (A.id is null OR A.type<>0)
 -- A.id IS NULL
 -- AND A.type <> 0 -- added for exclude a.type = 0
 AND B.state NOT IN (3,4,10)
 AND B.disable = 0

这意味着JOIN A.type不在0的位置以及您为查询计划的其他条件

答案 2 :(得分:0)

您可以通过这种方式使用连接而不是子查询获得所需的结果:

select  B.id
from    A right join B on A.ticket = B.id
where   B.state not in (3, 4, 10) and B.disable = 0
group by B.id
having count(case when A.ticket is not null and A.type = 0 then 1 end) = 0;

通过这种方式,您只考虑B中没有任何匹配行的B行或者有A.type = 0但没有匹配的行。

错误的预编辑答案

我会选择:

select  B.*
from    A right join B on A.ticket = B.id
where   B.state not in (3, 4, 10) and B.disable = 0 and coalesce(A.type, 1) <> 0

这样您只会考虑不加入或加入但没有A.type = 0的行。

请注意,根据您使用的数据库,coalesce函数可能必须替换为等效的函数。

答案 3 :(得分:0)

使用子查询来实现相同的查询并保持RIGHT JOIN。此方法也可能更快,因为它尝试从两个JOIN端的表中连接最少量的记录。

SELECT B2.* 
FROM 
  (SELECT ticket, type FROM A WHERE type=0) A2 
RIGHT JOIN 
  (SELECT * FROM B WHERE B.state NOT IN (3,4,10) AND B.disable = 0) B2 
ON A2.ticket = B2.id WHERE A2.ticket IS NULL;