【问题标题】:Move Columns to next if null如果为空,则将列移动到下一个
【发布时间】:2017-09-02 15:23:56
【问题描述】:

如果所需列为空,我想将颜色向前移动到下一列,但是我使用了 COALESCE 函数但无法获得预期结果

下面是我的表结构

ID.        Level1.  Level2.   Level3    Level5 
1.         Xyz.     Null.     Null.     Null
2.         Abc.     Xyz.      Null.     Null
3.         Mno.     Abc.      Xyz.      Null
4.         Ggg.     Mno.      Abc.      Xyz

预期结果如下

ID.        Level1.  Level2.   Level3    Level5 
1.         Null.    Null.     Null.     Xyz
2.         Null.    Null.     Abc.      Xyz
3.         Null.    Mno.      Abc.      Xyz
4.         Ggg.     Mno.      Abc.      Xyz

【问题讨论】:

  • 请像 Jason 的回答一样发布 dml,ddl,这很有帮助

标签: sql sql-server sql-server-2008 sql-server-2012 sql-server-2014


【解决方案1】:

虽然你可以用coalesce() 做到这一点,但另一种方法更简单(信不信由你):

select t.*, lv.*
from t outer apply
     (select max(case when l = 1 then lev end) as level5,
             max(case when l = 2 then lev end) as level4,
             max(case when l = 3 then lev end) as level3,
             max(case when l = 4 then lev end) as level2,
             max(case when l = 5 then lev end) as level1             
      from (select lev, row_number() over (order by l desc) as l
            from (values (1, level1), (2, level2), (3, level3), (4, level4), (5, level5) v(l, lev)
            where lev is not null
           ) l
      ) lv;

逻辑是取消透视每一行的数据并重新聚合非NULL 值。

【讨论】:

  • 我针对我的测试数据运行了您的解决方案。它没有将值向右移动,而是简单地将 L1 -> L4 的列顺序反转为 L4 -> L1 ...抱歉,找不到发布结果的方法,以便它们在该区域清晰可见...
  • 其实我之前弄错了……正确的值在正确的列下。他们以相反的顺序显示的事实让我失望。过错。
【解决方案2】:

看起来它正在产生预期的结果......

IF OBJECT_ID('tempdb..#TestDate', 'U') IS NOT NULL 
DROP TABLE #TestDate;

CREATE TABLE #TestDate (
    ID CHAR(2) NOT NULL,
    Level_1 VARCHAR(10) NULL,
    Level_2 VARCHAR(10) NULL,
    Level_3 VARCHAR(10) NULL,
    Level_4 VARCHAR(10) NULL
    );
INSERT #TestDate (ID, Level_1, Level_2, Level_3, Level_4) VALUES 
    ('1.', 'Xyz.', Null, Null, Null),
    ('2.', 'Abc.', 'Xyz.', Null, Null),
    ('3.', 'Mno.', 'Abc.', 'Xyz.', Null),
    ('4.', 'Ggg.', 'Mno.', 'Abc.', 'Xyz');

--  SELECT * FROM #TestDate td;

WITH 
    cte_NewLevel AS (
        SELECT 
            td.ID,lvl.LevelNum, lvl.LebelValue,
            NewLevel = 5 - COUNT(lvl.LebelValue) OVER (PARTITION BY td.ID ORDER BY lvl.LevelNum DESC ROWS UNBOUNDED PRECEDING)
        FROM
            #TestDate td
            CROSS APPLY ( VALUES (1, td.Level_1), (2, td.Level_2), (3, td.Level_3), (4, td.Level_4) ) lvl (LevelNum, LebelValue)
        )
SELECT 
    nl.ID,
    Level_1 = MAX(CASE WHEN nl.NewLevel = 1 THEN nl.LebelValue END),
    Level_2 = MAX(CASE WHEN nl.NewLevel = 2 THEN nl.LebelValue END),
    Level_3 = MAX(CASE WHEN nl.NewLevel = 3 THEN nl.LebelValue END),
    Level_4 = MAX(CASE WHEN nl.NewLevel = 4 THEN nl.LebelValue END)
FROM
    cte_NewLevel nl
GROUP BY
    nl.ID;

结果...

ID   Level_1    Level_2    Level_3    Level_4
---- ---------- ---------- ---------- ----------
1.   NULL       NULL       NULL       Xyz.
2.   NULL       NULL       Abc.       Xyz.
3.   NULL       Mno.       Abc.       Xyz.
4.   Ggg.       Mno.       Abc.       Xyz

【讨论】:

    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    • 2016-08-09
    相关资源
    最近更新 更多