JOIN中的SQL CASE返回额外的行

时间:2015-11-23 00:55:30

标签: sql sql-server tsql

我有以下两个表:

T1

Id        Value
NULL      A
NULL      B
NULL      C

T2

Id        Value
1         A
2         C
-2        Unmatched

我想使用CASE表达式加入Value,t1中所有在t2中都有相应行的行。对于那些不匹配的我想要默认为不匹配的行(-2)。我的预期输出是:

t1.Id     t1.Value     t2.Id     t2.Value
NULL      A            1         A
NULL      B            -2        Unmatched
NULL      C            2         C

但是使用以下脚本:

WITH t1
AS
(
    SELECT NULL AS Id,
           'A' AS Value
    UNION ALL
    SELECT NULL AS Id,
           'B' AS Value
    UNION ALL
    SELECT NULL AS Id,
           'C' AS Value
),
t2
AS
(
    SELECT 1 AS Id,
           'A' AS Value
    UNION ALL
    SELECT 2 AS Id,
           'C' AS Value
    UNION ALL
    SELECT -2 AS Id,
           'Not Matched' AS Value
)
SELECT *
FROM t1
    LEFT OUTER JOIN t2
        ON (CASE
                WHEN t1.Value = t2.Value
                    THEN t2.Id
                WHEN t1.Value IS NOT NULL
                    THEN -2
            END) = t2.Id;

我得到以下结果:

t1.Id     t1.Value     t2.Id     t2.Value
NULL      A            1         A
NULL      A            -2        Unmatched
NULL      B            -2        Unmatched
NULL      C            2         C
NULL      C            -2        Unmatched

我有一个简单的解决方法,可以做我需要的但是我的问题是为什么我似乎在我的案例表达式中得到这种行为?删除第二个WHEN会产生以下内容,这几乎符合要求:

t1.Id     t1.Value     t2.Id     t2.Value
NULL      A            1         A
NULL      B            NULL      NULL
NULL      C            2         C

2 个答案:

答案 0 :(得分:2)

要回答你的问题,即使它有其他匹配,每一行都匹配-2行。如果我简化ON子句只显示-2匹配,那就很清楚了:

SELECT *
FROM t1
JOIN t2
  ON CASE WHEN t1.Value IS NOT NULL THEN -2 END = t2.Id;

答案 1 :(得分:0)

正如JBrooks在他的回答中指出的那样,你的WHEN t1.Value IS NOT NULL将永远为真(因为t1.Value永远不会为NULL,因为这是你的连接的左侧)。

完全删除WHEN,而只是在select语句中执行ISNULL或COALESCE。

WITH t1
AS
(
    SELECT NULL AS Id,
           'A' AS Value
    UNION ALL
    SELECT NULL AS Id,
           'B' AS Value
    UNION ALL
    SELECT NULL AS Id,
           'C' AS Value
),
t2
AS
(
    SELECT 1 AS Id,
           'A' AS Value
    UNION ALL
    SELECT 2 AS Id,
           'C' AS Value
    UNION ALL
    SELECT -2 AS Id,
           'Not Matched' AS Value
)
SELECT t1.id, t1.value, ISNULL(t2.id, -2), ISNULL(t2.value,'Unmatched')
FROM t1
    LEFT OUTER JOIN t2 ON t1.value = t2.value
;

结果

NULL    A   1   A
NULL    B   -2  Unmatched
NULL    C   2   C