如何在多个列上应用相同的COALESCE参数

时间:2018-07-17 10:50:33

标签: sql sql-server

我必须在两个条件下联接两个表。我希望如果第二个条件不成立,但表1中有一个空白单元格,然后加入该行。如果第二个条件不成立,则返回零。

加入表1和表2-从表1中返回表2和第3、4和5列。

DECLARE @table1 TABLE (
     letter CHAR(1),
     num1 INT,
     num2 NUMERIC(5,2),
     num3 INT,
     num4 NUMERIC(5,2)
)  

DECLARE @table2 TABLE (
    letter CHAR(1),
    num1 INT
)
INSERT INTO @table1 VALUES      
    ('A', 1, 0.25, 10, 0.5),  
    ('A', 2, 0.50, 15, 0.75),  
    ('A', 3, 0.25, 20, 1),  
    ('A', null, 0.50, 25, 1.5),  
    ('B', 1, 0.25, 10, 0.5),  
    ('B', 2, 0.50, 15, 0.5),  
    ('B', 3, 0.25, 20, 0.75)

INSERT INTO @table2 VALUES   
    ('A', 1),  
    ('A', 2),  
    ('A', 3),  
    ('A', 5),  
    ('B', 1),  
    ('B', 2),  
    ('B', 3),  
    ('B', 5)   

类似的东西:

SELECT t2.*,     
    COALESCE(  
        (SELECT TOP 1 num2, num3, num4 FROM @table1 WHERE letter = t2.letter AND num1 = t2.num1),   
        (SELECT TOP 1 num2, num3, num4 FROM @table1 WHERE letter = t2.letter AND num1 IS NULL),   
        0  
    ) AS missing_number  
FROM @table2 t2

所需的输出:

(A, 1, 0.25, 10, 0.5),  
(A, 2, 0.50, 15, 0.75),  
(A, 3, 0.25, 20, 1),  
(A, 5, 0.50, 25, 1.5),  
(B, 1, 0.25, 10, 0.5),  
(B, 2, 0.50, 15, 0.5),  
(B, 3, 0.25, 20, 0.75),  
(B, 5, 0.00, 0, 0.00)  

4 个答案:

答案 0 :(得分:2)

SELECT t2.*, 
    COALESCE(t1.num2, t3.num2, 0) AS num2, 
    COALESCE(t1.num3, t3.num3, 0) AS num3, 
    COALESCE(t1.num4, t3.num4, 0) AS num4
FROM @table2 t2
LEFT OUTER JOIN @table1 t1 ON t2.letter = t1.letter AND t2.num1 = t1.num1
LEFT OUTER JOIN @table1 t3 ON t2.letter = t3.letter AND t3.num1 IS NULL

在SQL中,无法知道表连接期间当前行是否匹配。当来自@ table2的行与某列不匹配时,我们无法表示将@ table2连接到@ table1的可为空的特殊行(其中@ table1.num1为null)。需要多个联接。第二个连接基于按列字母和num1的常规连接。 尝试以下查询将给出预期的结构。

SELECT *
FROM @table2 t2
LEFT OUTER JOIN @table1 t1 ON t2.letter = t1.letter AND t2.num1 = t1.num1

然后将特殊行与@ table2中的每一行匹配。

答案 1 :(得分:2)

尝试:

SELECT tt.letter,
    tt.num1,
    COALESCE(tt.num2, t1.num2, 0.00) AS num2,
    COALESCE(tt.num3, t1.num3, 0) AS num3,
    COALESCE(tt.num4, t1.num4, 0.00) AS num4
FROM(
    SELECT t2.letter,
        t2.num1,
        t1.num2,
        t1.num3,
        t1.num4
    FROM @table2 t2
    LEFT JOIN @table1 t1 ON t2.letter = t1.letter
        AND t2.num1 = t1.num1) tt
    LEFT JOIN @table1 t1 ON t1.letter = tt.letter
        AND t1.num1 IS NULL

输出:

letter  num1    num2    num3    num4
A       1       0.25    10      0.50
A       2       0.50    15      0.75
A       3       0.25    20      1.00
A       5       0.50    25      1.50
B       1       0.25    10      0.50
B       2       0.50    15      0.50
B       3       0.25    20      0.75
B       5       0.00    0       0.00

答案 2 :(得分:1)

我认为这可行

SELECT DISTINCT
     T2.letter
    ,T2.num1
    ,num2 = COALESCE(T1.num2, t11.num2,0)
    ,num3 = COALESCE(T1.num3, t11.num3, 0)
    ,num4 = COALESCE(T1.num4, t11.num4,0)
FROM @table2 T2
LEFT JOIN @table1 T1 ON t1.letter = t2.letter AND T1.num1 = T2.num1
LEFT JOIN(
    SELECT * FROM @table1 TA1 WHERE TA1.num1 IS NULL
) T11 ON t11.letter = t2.letter

输出

letter  num1    num2    num3    num4
A       1       0.25    10      0.50
A       2       0.50    15      0.75
A       3       0.25    20      1.00
A       5       0.50    25      1.50  --Null rows
B       1       0.25    10      0.50
B       2       0.50    15      0.50
B       3       0.25    20      0.75
B       5       0.00    0       0.00  --Null rows

答案 3 :(得分:1)

我采用的方法是将每个“规则”本身编码为查询,然后将{3}的结果UNION在一起。我个人发现这样的方法不仅使一开始的编码更容易,而且以后也易于维护:

SELECT t1.letter, t1.num1, t1.num2, t1.num3, t1.num4
  FROM table1 t1
 WHERE EXISTS ( SELECT *
                  FROM table2 t2
                 WHERE t2.letter = t1.letter
                   AND t2.num1 = t1.num1 )
UNION
SELECT t2.letter, t2.num1, t1.num2, t1.num3, t1.num4
  FROM table1 t1, table2 t2
 WHERE t2.letter = t1.letter
       AND t1.num1 IS NULL
       AND NOT EXISTS ( SELECT * 
                          FROM table1 
                         WHERE letter = t2.letter
                               AND num1 = t2.num1 )
UNION
SELECT t2.letter, t2.num1, 0 AS num2, 0 AS num3, 0 AS num4
  FROM table1 t1, table2 t2
 WHERE t2.letter = t1.letter
       AND NOT EXISTS ( SELECT * 
                          FROM table1 
                         WHERE letter = t2.letter
                               AND num1 = t2.num1 )
       AND NOT EXISTS ( SELECT * 
                          FROM table1 
                         WHERE letter = t2.letter
                               AND num1 IS NULL );