具有CASE语句的JOIN ON子句取决于if字段是否为NULL?

时间:2014-02-28 17:49:30

标签: sql sql-server sql-server-2008

我正在尝试使用带有2个ID的表进行简单的LEFT JOIN - 基本上是ID和Sub-ID。每行都有一个ID,但不一定是Sub-ID。当存在子ID时,我想基于此加入,如果不加入ID。我想象

之类的东西
SELECT ...
FROM tablename a
LEFT JOIN tablename b
 ON CASE WHEN SUB_ID IS NOT NULL THEN
  a.SUB_ID = b.SUB_ID
 ELSE
  a.ID = b.ID END
AND 
  a.otherfield = b.otherfield

但是我无法得到这样的东西,所以我不得不用UNION做一个查询(一个加入了SUB_ID WHERE SUB_ID IS NOT NULL而另一个加入了ID WHERE SUB_ID IS NULL。)它工作,但我无法想象没有办法做到这一点。如果有帮助,我的ID和SUB_ID值如下所示:

ID           SUB_ID
10000        NULL
10001        NULL 
10001        10001-3
10001        10001-5
10014        NULL   

有关如何在不执行UNION的情况下实现此目的的任何建议?在此先感谢!!

5 个答案:

答案 0 :(得分:2)

这对你有用。

SELECT ...
FROM tablename a
    LEFT JOIN tablename b
        ON ((b.SUB_ID IS NOT NULL AND a.SUB_ID = b.SUB_ID) OR 
            (a.ID = b.ID))
        AND a.otherfield = b.otherfield

答案 1 :(得分:1)

我们可以将COALESCE用于此目的:

SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON COALESCE(a.SUB_ID,a.ID) = COALESCE(b.SUB_ID,b.ID)

COALESCE从左侧返回first not null参数的值。

以下是SQL Fiddle

的代码

答案 2 :(得分:0)

你可以加入桌子两次:<​​/ p>

SELECT ...
FROM tablename a
    LEFT JOIN tablename b
        ON a.SUB_ID = b.SUB_ID
        AND a.otherfield = b.otherfield
    LEFT JOIN tablename c
        ON a.ID = b.ID
        AND a.SUB_ID IS NULL
        AND a.otherfield = c.otherfield

然后使用ISNULL获取列,例如

ColumnName = ISNULL(b.ColumnName, c.ColumnName)

这取决于您的索引,但我怀疑这可能比使用条件连接子句更好地进行优化。

答案 3 :(得分:0)

有趣。

 SELECT ...
 FROM tablename a
    LEFT JOIN tablename b
       ON (
         a.SUB_ID = b.SUB_ID
         OR (a.SUB_ID IS NULL AND b.SUB_ID IS NULL AND a.ID = b.ID)
       )
       AND a.otherfield = b.otherfield

这可能会奏效。不过,它不会很快。

根据您的数据状态和您想要实现的目标,您可能希望将join子句更改为

       ON (
             a.SUB_ID = b.SUB_ID
         OR (a.SUB_ID IS NULL AND a.ID = b.ID)
         OR (b.SUB_ID IS NULL AND a.ID = b.ID)
       )
       AND a.otherfield = b.otherfield

......相反。

答案 4 :(得分:0)

尝试这样的事情:

SELECT *
FROM TABLENAME A
LEFT JOIN TABLENAME B
    ON (A.SUB_ID IS NOT NULL AND A.SUB_ID = B.SUB_ID)
    OR (A.SUB_ID IS NULL AND A.ID = B.ID)