以下问题:
我有一个表(客户端),它拥有多个具有相同用户名的记录(不幸的是,它是软件前端的限制)。当我在用户名上加入该表时,它显然会返回多行。通常我使用ROW_NUMBER(),按照我想要的字段上的用户名和顺序进行分区,然后加入以将结果集限制为1并返回所需的列,这在过去一直运行良好。但是,我试图以前所未有的方式使用它...我按用户名进行分区,并按记录最后更新的日期排序,以便返回第三个字段,在本例中为地址。观察下表结果:
Username|UpdatedDate|Address
JSmith |10-10-14 |NULL
JSmith |05-24-14 |1 Main Street
对象是返回最新记录,但如果最新记录不包含地址,则从上一记录中获取地址。
这可能吗?
编辑:
@Gordon ......也许我误解了一些东西,但在第一种方法中,订购时不考虑最后更新的日期。如果表格如下:
JSmith|10-10-14|1 Main
JSmith|04-20-14|1 Main
JSmith|01-10-13|5 Main
它将为所有行返回1。最终目标是,如果只有一条记录,那就抓住那条记录。如果有多条记录,要获取最新记录,但如果地址为NULL,请使用地址获取下一个最新记录。
答案 0 :(得分:1)
只需使用正确的row_number()
逻辑:
select c.*
from (select c.*,
row_number() over (partition by username
order by (case when address is not null then 1 else 2 end), UpdatedDate desc
) as seqnum
from clients c
) c
where seqnum = 1;
当然,如果您不介意过滤掉没有地址的username
,您可以使用:
select c.*
from (select c.*,
row_number() over (partition by username
order by UpdatedDate desc
) as seqnum
from clients c
where address is not null
) c
where seqnum = 1;
但你最终可能会失去一些记录。
答案 1 :(得分:0)
除了row_number()之外,还使用apply运算符定位最近的地址,以便获得最新数据的整行以及最新的地址,即使在最新的地址恰好为空的情况下也是如此行。
SELECT
c.*
FROM (
SELECT
c.*
, ROW_NUMBER() OVER (PARTITION BY username
ORDER BY UpdatedDate DESC) AS seqnum
, COALESCE(c.address, oa.lastaddress) AS lastaddress
FROM clients c
OUTER APPLY (
SELECT TOP (1)
address AS lastaddress
FROM clients c2
WHERE c.username = c2.username
AND c2.adress IS NOT NULL
ORDER BY
UpdatedDate DESC
) oa
) c
WHERE seqnum = 1;