我有两个表TABLE_A
和TABLE_B
,其中已加入的列为员工编号EMPNO
。
我想做一个正常的左外连接。但是,TABLE_B
有一些软删除的记录(status='D'
),我希望将其包括在内。只是为了澄清,TABLE_B
可以有活动记录(status = null / a / anything)以及已删除的记录,在这种情况下,我不希望我的结果中有该员工。但是,如果TABLE_B
中只有员工的删除记录,我希望员工被包含在结果中。我希望我的要求是明确的。 (我可以做一个冗长的qrslt类型的东西,得到我想要的东西,但我认为必须有一个更优化的方法,使用连接语法这样做)。非常感谢任何建议(即使没有加入)。他的新手正在尝试以下查询而没有预期的结果:
SELECT TABLE_A.EMPNO
FROM TABLE_A
LEFT OUTER JOIN TABLE_B ON TABLE_A.EMPNO = TABLE_B.EMPNO AND TABLE_B.STATUS<>'D'
非常感谢任何帮助。
答案 0 :(得分:2)
只是澄清一下 - 除非表B中的行有其他而不是'D',否则应显示TABLE_A中的所有记录?
你需要在B上至少有一个非空列(我将以'B.ID'为例,这种方法应该有效):
SELECT TABLE_A.EMPNO
FROM TABLE_A
LEFT OUTER JOIN TABLE_B ON
(TABLE_A.EMPNO = TABLE_B.EMPNO)
AND (TABLE_B.STATUS <> 'D' OR TABLE_B.STATUS IS NULL)
WHERE
TABLE_B.ID IS NULL
也就是说,颠倒你可能想到的逻辑 - 只有在你有排除 TABLE_A条目的行的情况下才加入TABLE_B,然后在末尾使用IS NULL来排除这些。这意味着只包括那些不匹配的那些(在TABLE_B中没有行,或者只有'D'行)。
替代方案可能是
SELECT TABLE_A.EMPNO
FROM TABLE_A
WHERE NOT EXISTS (
SELECT * FROM TABLE_B
WHERE TABLE_B.EMPNO = TABLE_A.EMPNO
AND (TABLE_B.STATUS <> 'D' OR TABLE_B.STATUS IS NULL)
)
答案 1 :(得分:0)
啊crud,这显然有效&gt;&lt;
SELECT TABLE_A.EMPNO
FROM TABLE_A
LEFT OUTER JOIN TABLE_B ON TABLE_A.EMPNO = TABLE_B.EMPNO
where TABLE_B.STATUS<>'D'
如果你们有任何额外的信息可以加入,请随意。
更新: 经过一段时间后看到这个问题并认为我会添加更多有用的信息:此链接有关于ANSI语法的良好信息 - http://www.oracle-base.com/articles/9i/ANSIISOSQLSupport.php
特别是链接页面中的这部分内容非常丰富:
可以将连接中的额外过滤条件添加到使用AND以形成复杂连接。当需要过滤条件来限制外部连接时,通常需要这些。如果这些过滤条件放在WHERE子句中,并且外部联接返回过滤器列的NULL值,则该行将被丢弃。如果过滤条件被编码为连接的一部分,则可以避免这种情况。
答案 2 :(得分:0)
以下查询将为您提供未删除的员工记录,或只有员工只有已删除的记录。
select
a.*
from
table_a a
left join table_b b on
a.empno = b.empno
where
b.status <> 'D'
or (b.status = 'D' and
(select count(distinct status) from table_b where empno = a.empno) = 1)
这是在ANSI SQL中,但如果我知道你的RDBMS,我可以提供一个更具体的解决方案。
答案 3 :(得分:0)
SELECT A.*, B.*
FROM
Table_A A
INNER JOIN Table_B B
ON A.EmpNo = B.EmpNo
WHERE
NOT EXISTS (
SELECT *
FROM Table_B X
WHERE
A.EmpNo = X.EmpNo
AND X.Status <> 'D'
)
我认为这样做了。不需要左连接,因为您只想包含所有(至少一个)已删除行的员工。
答案 4 :(得分:0)
这就是我理解这个问题的方法。您只需要包括满足以下任一条件的员工:
员工在TABLE_B
中只有(软)删除的行;
员工在TABLE_B
;
员工在TABLE_B
中根本没有行。
换句话说,如果员工在TABLE_B
中同时包含已删除和未删除的行,请忽略该员工,否则请将其包括在内。
这就是我认为可以解决的问题:
SELECT DISTINCT a.EMPNO
FROM TABLE_A a
LEFT JOIN TABLE_B b1 ON a.EMPNO = b1.EMPNO
LEFT JOIN TABLE_B b2 ON b1.EMPNO = b2.EMPNO
AND (b1.STATUS = 'D' AND (b2.STATUS <> 'D' OR b2 IS NULL) OR
b2.STATUS = 'D' AND (b1.STATUS <> 'D' OR b1 IS NULL))
WHERE b2.EMPNO /* or whatever non-nullable column there is */ IS NULL
或者,您可以使用分组:
SELECT a.EMPNO
FROM TABLE_A a
LEFT JOIN TABLE_B b ON a.EMPNO = b1.EMPNO
GROUP BY a.EMPNO
HAVING 0 IN (COUNT(CASE b.STATUS WHEN 'D' THEN 1 ELSE NULL END),
COUNT(CASE b.STATUS WHEN 'D' THEN NULL ELSE 1 END))