简化COALESCE查询

时间:2016-05-23 17:34:33

标签: sql sql-server coalesce

我正在寻求简化下面的查询,而我无法绕过另一种解决方案,但我认为必须有一个可用。

目标是从Col_C中检索Col_D。 如果Col_D返回NULL,我想从Col_B获得Col_D。 如果返回NULL,则再次上升阶梯并从Col_A获取Col_D。但只有在Col_B和Col_C为NULL的情况下。

a = MyModule
a.function()

查询

Table_A
Col_A   Col_B   Col_C   Col_X
L000    3200    3220    0000

Table_B
Col_A   Col_B   Col_C   Col_D
L000    NULL    NULL    3256
L000    3200    NULL    6483
L000    3200    3210    7213
L000    3200    3220    NULL
L000    3200    3230    9462

预期产出

DECLARE @X nvarchar(4) = '0000'

DECLARE @A nvarchar(4), @B nvarchar(4), @C nvarchar(4)
SELECT @A = Col_A, @B = Col_B, @C = Col_C FROM [Table_A] 
WHERE [Col_X] = @X

SELECT COALESCE(
(SELECT [Col_D] FROM [Table_B] WHERE Col_C = @C AND Col_B = @B AND Col_A = @A), 
(SELECT [Col_D] FROM [Table_B] WHERE Col_C IS NULL AND Col_B = @B AND Col_A = @A), 
(SELECT [Col_D] FROM [Table_B] WHERE Col_C IS NULL AND Col_B IS NULL AND Col_A = @A)
) AS Col_D

编辑:添加了Table_A和预期输出

3 个答案:

答案 0 :(得分:1)

SQL Server在排序降序时排序最后的空值。因此,您所要做的就是获取所有可能的候选记录,即:col_d不能为null,col_a必须匹配,col_b和col_c必须匹配或为null。订单下降并占据最上一行。

select col_d
from table_b
where col_d is not null
and col_a = @a
and (col_b = @b or col_b is null)
and (col_c = @c or col_c is null)
order by col_b desc, col_c desc;

完整查询,包括table_a:

select b.col_d
from (select * from table_a where col_x = @x) a
join table_b b on  b.col_d is not null
               and b.col_a = a.col_a
               and (b.col_b = a.col_b or b.col_b is null)
               and (b.col_c = a.col_c or b.col_c is null)
order by b.col_b desc, b.col_c desc;

答案 1 :(得分:0)

你想要一行,优先考虑。所以:

Select cold
From t
Where (cold = @a or colc is null) and
       (Colb = @b or colb is null)
Order by (case when colc is not null then 1 else 2 end),
         (Case when colc is not null then 1 else 2 end)
Fetch first 1 row only;

根据数据库的不同,您可以使用limit或top来获取一行。

答案 2 :(得分:0)

在你通过提供预期的产出来澄清意图之前,戈登可能已经回答了。请注意,我的查询在逻辑上与原始查询不同。它将返回Col_A = @A所在的最小空行。例如,您的查询将排除Col_C和Col_A具有值的结果,但Col_B为空,此查询不会。此外,如果没有行Col_A = @A,则它将返回空结果集而不是NULL值。

如果新查询在逻辑上必须与原始查询完全相同,那么我不确定它是否可以简化为更容易阅读,尽管可能有一个更“复杂”的解决方案表现更好。 / p>

SELECT TOP 1 Col_D
FROM Table_B
WHERE Col_A = @A
ORDER BY CASE WHEN Col_B IS NOT NULL -- Sort null Col_B values to the bottom
                THEN 1 
                ELSE 0 
         END,
         CASE WHEN Col_C IS NOT NULL -- Sort null Col_C values to the bottom
                THEN 1 
                ELSE 0 
         END,
         CASE WHEN Col_D IS NOT NULL -- Sort null Col_D values to the bottom
                THEN 1 
                ELSE 0 
         END