组中每列的最后一个值,每组一行

Last value per column in group, one row per group

这应该很简单,但由于某种原因我卡住了。考虑以下数据:

KEY1  KEY2  COL1    COL2    COL3
--------------------------------------
1     1     A       7       (null)
1     2     A       8       (null)
1     3     (null)  7       (null)
2     2     (null)  (null)  4
2     4     B       6       (null)
3     1     A       B       (null)

(KEY1是Id,KEY2是代号,实际有30个左右的数据列,这里为了简单只列出3个。)

我想为每个 Id 获取一行,并为每一列获取最后一个非空值。换句话说...

KEY1  COL1    COL2    COL3
----------------------------
1     A       7       (null)
2     B       6       4
3     A       B       (null)

我尝试了以下方法,但它似乎除了回显我所有的行之外什么也没做。

SELECT key1,
       LAST_VALUE(col1) OVER (PARTITION BY key1 ORDER BY key2 ASC) AS col1,
       LAST_VALUE(col2) OVER (PARTITION BY key1 ORDER BY key2 ASC) AS col2,
       LAST_VALUE(col3) OVER (PARTITION BY key1 ORDER BY key2 ASC) AS col3
    FROM test1

(这是针对 SQL Server 2012 和 SQL Server Express。)

SQL 服务器(还)不支持 window 函数的 IGNORE NULL 选项。一种方法是使用条件聚合。这需要为列智能生成序列号,以确保将序列的值“1”分配给非 NULL 值。

这是一个应该执行此操作的查询:

select t1.key1,
       max(case when seqnum1 = 1 then col1 end) as col1,
       max(case when seqnum2 = 1 then col2 end) as col2,
       max(case when seqnum3 = 1 then col3 end) as col13
from (select t1.*,
             row_number() over (partition by key1
                                order by (case when col1 is not null then 1 else 2 end),
                                         key2 desc
                               ) as seqnum1,
             row_number() over (partition by key1
                                order by (case when col2 is not null then 1 else 2 end),
                                         key2 desc
                               ) as seqnum2,
             row_number() over (partition by key1
                                order by (case when col3 is not null then 1 else 2 end),
                                         key2 desc
                               ) as seqnum3
      from test1 t1
     ) t1
group by t1.key1

如果我对要求的理解正确,这应该行得通吗?根据数据/列的数量,可能会非常昂贵。

select
   key1,
   (select top 1 col1 from test1 t2 where t.key1 = t2.key1 and col1 is not null order by key2 desc) as col1,
   (select top 1 col2 from test1 t2 where t.key1 = t2.key1 and col2 is not null order by key2 desc) as col2,
   (select top 1 col3 from test1 t2 where t.key1 = t2.key1 and col3 is not null order by key2 desc) as col3
from 
   (select distinct key1 from test1) t