2

我有两个表TABLE_A,并将TABLE_B连接列作为员工编号EMPNO

我想做一个正常的左外连接。但是,TABLE_B某些记录是软删除的 ( status='D'),我希望将这些记录包括在内。澄清一下,TABLE_B可能有活动记录(状态= 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' 

非常感谢任何帮助。

4

5 回答 5

3

只是为了澄清 - 应该出现来自 TABLE_A 的所有记录,除非表 B 中的行具有除“D”以外的雕像?

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)
)
于 2009-08-24T12:22:58.860 回答
0

啊,这显然行得通><

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 值,则该行将被丢弃。如果过滤条件被编码为连接的一部分,则可以避免这种情况。

于 2009-08-24T12:16:42.087 回答
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,我可以提供一个更具体的解决方案,可能会更优雅一些。

于 2009-08-24T12:21:37.457 回答
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'
    )

我认为这可以解决问题。不需要左连接,因为您只想包含所有(和至少一个)已删除行的员工。

于 2011-06-10T07:23:57.333 回答
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))
于 2011-06-10T08:34:11.427 回答