sql server合并行并获取最新值

时间:2015-02-26 10:20:01

标签: sql sql-server

我有一张这样的表,

Id  A       B       C       D     touchedwhen
1   NULL    yes     NULL    yes   2015-02-26 14:10:01.870
1   NULL    NULL    no      no    2015-02-26 14:10:40.370

并且需要将它们合并到这样的一行,

Id  A       B       C       D     touchedwhen
1   NULL    yes     no      no    2015-02-26 14:10:40.370.

注意:如果两行中都存在值,请按日期采用最新值..

尝试了这个问题:

select id,
max(a),
max(b),
max(c),
max(d), -- data in both rows hence take the latest
max(touchedwhen)
from 
[dbo].[Table_1]
group by id;

2 个答案:

答案 0 :(得分:0)

如果你只是在寻找每个id的最后一个值,你可以使用:

last_value(a) over(
    partition by id 
    order by touchedwhen desc 
    rows between unbounded preceding and unbounded following) as a

但您正在寻找每id not null的最后一个值。我唯一能想到的是一个四部分连接,每个子查询计算a, b, c, d的最新非空值:

select  ids.id
,       a.a
,       b.b
,       c.c
,       d.d
,       ids.tw
from    (
        select  id
        ,       max(touchedwhen) as tw
        from    YourTable
        group by
                id
        ) ids
left join
        (
        select  row_number() over (
                    partition by id
                    order by touchedwhen desc) rn
        ,       a
        ,       id
        from    YourTable
        where   a is not null
        ) a
on      a.id = ids.id
        and a.rn = 1
left join
        (
        select  row_number() over (
                    partition by id
                    order by touchedwhen desc) rn
        ,       b
        ,       id
        from    YourTable
        where   b is not null
        ) b
on      b.id = ids.id
        and b.rn = 1
left join
        (
        select  row_number() over (
                    partition by id
                    order by touchedwhen desc) rn
        ,       c
        ,       id
        from    YourTable
        where   c is not null
        ) c
on      c.id = ids.id
        and c.rn = 1
left join
        (
        select  row_number() over (
                    partition by id
                    order by touchedwhen desc) rn
        ,       d
        ,       id
        from    YourTable
        where   d is not null
        ) d
on      d.id = ids.id
        and d.rn = 1

答案 1 :(得分:0)

-- Get all latest values in one row for each primary key
WITH CTE(row_num, Id, A, B, C, D, touchedwhen) AS (
    SELECT ROW_NUMBER() OVER(PARTITION BY Id ORDER BY touchedwhen DESC), Id, A, B, C, D FROM Table_1)
UPDATE CTE SET
    A = (SELECT TOP 1 t.A FROM Table_1 t WHERE t.A IS NOT NULL AND t.Id = CTE.Id ORDER BY t.touchedwhen DESC),
    B = (SELECT TOP 1 t.B FROM Table_1 t WHERE t.B IS NOT NULL AND t.Id = CTE.Id ORDER BY t.touchedwhen DESC),
    C = (SELECT TOP 1 t.C FROM Table_1 t WHERE t.C IS NOT NULL AND t.Id = CTE.Id ORDER BY t.touchedwhen DESC),
    D = (SELECT TOP 1 t.D FROM Table_1 t WHERE t.D IS NOT NULL AND t.Id = CTE.Id ORDER BY t.touchedwhen DESC)
    WHERE row_num = 1

-- Delete extra rows per primary key after copying latest values to one row
WITH CTE(row_num) AS (
    SELECT ROW_NUMBER() OVER(PARTITION BY Id ORDER BY touchedwhen DESC) FROM Table_1)
DELETE FROM CTE WHERE row_num > 1