如果为null,则将列移动到下一个

时间:2017-09-02 15:23:56

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

如果所需的列为null,我想将颜色向前移动到下一列但是我使用了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

2 个答案:

答案 0 :(得分: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值。

答案 1 :(得分:1)

这看起来好像产生了预期的效果......

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