【问题标题】:Simplify COALESCE query简化 COALESCE 查询
【发布时间】:2016-05-24 05:33:48
【问题描述】:

我希望简化下面的查询,但我无法解决替代解决方案,但我认为必须有一个可用的解决方案。

目标是从 Col_C 中检索 Col_D。 如果 Col_D 返回 NULL,我想从 Col_B 获取 Col_D。 如果返回 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 和预期输出

【问题讨论】:

  • “从 Col_C 获取 Col_D”是什么意思?所有这些都是 Table_B 中的列对吧?
  • 你能包含预期的输出吗?
  • 检索 Col_D 值,其中 Table_B.Col_C = Table_A.Col_C。 @n8wrl 这有帮助吗?
  • @CodeDifferent 添加了 Table_A 和预期输出以进行澄清

标签: sql sql-server coalesce


【解决方案1】:

按降序排序时,SQL Server 将空值排在最后。所以你要做的就是获取所有可能的候选记录,即: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;

【讨论】:

  • 优秀。完全按照我的需要工作,特别是能够获得所有值(如果需要),而不仅仅是前 1 个。谢谢。
【解决方案2】:

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

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

【讨论】:

  • 不明白这里的逻辑。你能澄清一下吗?
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 2022-01-08
    • 2012-09-20
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多