简化 COALESCE 查询

Simplify COALESCE query

我想简化下面的查询,但我想不出替代解决方案,但我认为必须有一个可用的解决方案。

objective是从Col_C中检索Col_D。 如果 Col_D returns NULL,我想从 Col_B 得到 Col_D。 如果 returns NULL,再次上梯子并从 Col_A 得到 Col_D。但仅在 Col_B 和 Col_C 为 NULL 的情况下。

表格

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

预期输出

Col_D
6483

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

你想要一排,优先。所以:

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 来获取一行。

Gordon 可能在您通过提供预期输出来阐明意图之前就已经回答了。请注意,我的查询在逻辑上与您的原始查询不同。它将 return 具有最少空值的行 Col_A = @A。例如,您的查询将排除 Col_C 和 Col_A 具有值但 Col_B 为空的结果,此查询不会。此外,如果 Col_A = @A 中没有行,它将 return 空结果集而不是 NULL 值。

如果新查询必须在逻辑上与原始查询相同,那么我不确定是否可以简化它以使其更易于阅读,尽管可能有更多 "complicated" 解决方案表现更好。

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

SQL 服务器在降序排序时最后对空值进行排序。所以你要做的就是获取所有可能的候选记录,即:col_d不能为空,col_a必须匹配,col_b和col_c必须匹配或为无效的。降序排列并取顶行。

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;