【问题标题】:Dynamically pass columns to COALESCE动态地将列传递给 COALESCE
【发布时间】:2014-01-18 12:18:03
【问题描述】:

我需要一些关于 COALESCE 的帮助。

语法:COALESCE(Col1,Col2,Col3...) 这意味着每次我都必须将列名写在里面作为参数。

我的问题是我们可以动态地将列名传递给这个函数吗?因为我的表格中的列数不断变化。

谢谢, 席德

【问题讨论】:

  • 听起来你的设计可能没有标准化。如果列数不断变化,并且这些列代表的内容足够相似,您可以将COALESCE 与它们一起使用。 Col1,Col2,Col3等代表什么?
  • 嗨 Martin - 每列都包含父子元素中的元数据,但采用不规则的层次结构(阶梯)格式。由于有些单元格为 NULL,所以我试图将数据向左移动并填充空单元格。现在由于层次结构的变化,我可能每次都有不同的列数。
  • 请提供您的数据样本和期望的结果。

标签: sql sql-server coalesce


【解决方案1】:

听起来你有一堆列,你想将值移到左边,NULLs 到右边。

您可以通过计算每个值之前的非 NULL 值的数量,然后使用 case 语句来分配值来做到这一点。下面展示了四列的代码:

select (case when col1_n = 1 then col1
             when col2_n = 1 then col2
             when col3_n = 1 then col3
             when col4_n = 1 then col4
        end) as col1,
       (case when col2_n = 2 then col2
             when col3_n = 2 then col3
             when col4_n = 2 then col4
        end) as col2,
       (case when col3_n = 3 then col3
             when col4_n = 3 then col4
        end) as col3,
       (case when col4_n = 4 then col4
        end) as col4
from (select t.*,
             (case when col1 is not null then 1 end) as col1_n,
             ((case when col1 is not not null then 1 else 0 end) +
              (case when col2 is not null then 1 end)
             ) as col2_n,
             ((case when col1 is not not null then 1 else 0 end) +
              (case when col2 is not null then 1 else 0 end) +
              (case when col3 is not null then 1 end)
             ) as col3_n,
             ((case when col1 is not not null then 1 else 0 end) +
              (case when col2 is not null then 1 else 0 end) +
              (case when col3 is not null then 1 else 0 end) +
              (case when col4 is not null then 1 end)
             ) as col4_n             
      from t
     ) t;

您可以在 SQL Fiddle (here) 上看到这项工作。

如果每个 for 都有一个唯一的 id,您还可以取消透视数据,使用 row_number() 并重新透视数据。

【讨论】:

  • 感谢戈登的回复。似乎上面的代码适用于已知(固定)数量的列?我表中的列数不断变化。你能告诉我是否可以以某种方式将列动态传递给 COALESCE?
  • @user3209759 。 . .表具有固定数量的列,即 SQL 定义。听起来您可能需要动态 SQL 或重新设计应用程序。从表中添加和删除列的应用程序听起来像是一个糟糕的设计。
  • 我的表最多有 20 列。其中可以说我得到了 10 列的数据,剩余的单元格将被 NULL 替换。我想我将不得不在 COALESCE 中将 Col1 硬编码为 col20,而不是传递非 NULL 的列。我还将看到您建议的动态 SQL 选项。谢谢...
  • @user3209759 。 . .然后你的表有 20 列。您可以将上述想法扩展到 20 列。最好有一个包含 id 列的表和一个包含值的第二列 - 一种数据的规范化方法。
  • 我正在尝试这个: SET @Stmt2 = 'Update .dbo. SET Column'+CAST(@Counter AS VARCHAR)+ '=' + 'COALESCE(Column1, Column2 , Column3, Column4, Column5) 其中 Column'+CAST(@Counter AS VARCHAR)+'= NULL' exec(@Stmt2)。它正在运行但不影响任何行。知道为什么吗?
【解决方案2】:

如果您不想写列名,Try 可以这样做。
这将显示所有列值都为空时的所有行,除了您指定的列(IgnoreThisColumn1 和 IgnoreThisColumn2)。

DECLARE @query NVARCHAR(MAX);

SELECT @query = ISNULL(@query+', ','') + [name] 
                FROM  sys.columns 
                WHERE object_id = OBJECT_ID('yourTableName') 
                AND  [name] != 'IgnoreThisColumn1' 
                AND  [name] !=  'IgnoreThisColumn2';

SET @query = N'SELECT * FROM TmpTable WHERE COALESCE('+ @query +') IS NULL';

EXECUTE(@query)

结果

如果您不希望除您指定的列之外的所有列都为空时的行,您可以简单地使用IS NOT NULL 而不是IS NULL

SET @query = N'SELECT * FROM TmpTable WHERE COALESCE('+ @query +') IS NOT NULL';

结果

[

【讨论】:

    猜你喜欢
    • 2021-06-23
    • 2020-08-04
    • 2021-12-28
    • 1970-01-01
    • 2018-05-28
    • 1970-01-01
    • 2019-10-25
    • 2021-06-25
    • 2012-07-30
    相关资源
    最近更新 更多