让我们考虑下表。
Id(PK, int) | DocDate(long) | Sender(varchar) | Recipient(varchar) | PeriodStart(long) | PeriodEnd(long)
对于每个Sender
,Recipient
,PerdiodStart
,PeriodEnd
,我正在不同的时间点写入多个条目。所以DocDate
不同。
现在,我要选择最新DocDate
,foreach Sender
,Recipient
,PeriodStart
,PerdiodEnd
的ID。我自己发现的唯一解决方案是使用CTE。
with prevFilter as (
select max(DocDate), Sender, Recipient, PeriodStart, PeriodEnd
from Table
group
by Sender, Recipient, PeriodStart, PeriodEnd
)
select Id
from Table t
inner
join prevFilter pf
on pf.DocDate = t.DocDate
and pf.Sender = t.Sender
and pf.Recipient = t.Recipient
and pf.PeriodStart = t.PeriodStart
and pf.PeriodEnd = t.PeriodEnd
您现在可能会认为,此查询的性能很差,但我可以使用聚簇索引来改进它。
但我想知道,如果没有更快更优雅的解决方案来解决这个问题。任何人都可以提供吗?
答案 0 :(得分:4)
您可以使用CTE和ROW_NUMBER
:
with prevFilter as (
select Id,
RN = ROW_NUMBER() OVER(PARTITION BY Sender, Recipient, PerdiodStart, PeriodEnd
ORDER BY DocDate DESC)
from Table
)
select Id
from prevFilter t
where RN = 1
答案 1 :(得分:1)
您可以使用SQL Server排名函数来隔离DocDate
的每个组合的最高Sender,Recipient, PeriodStart, PeriodEnd
的记录,然后过滤:
Select * from (
select *, row_number() over (partition by Sender,
Recipient, PeriodStart, PeriodEnd
order by DocDate desc) as ranker
from Table
) where ranker = 1
答案 2 :(得分:1)
Lamak有正确的想法,但有一些错误。这个版本应该可以工作。
with prevFilter as (
select Id,
RN = ROW_NUMBER() OVER(
PARTITION BY Sender, Recipient, PeriodStart, PeriodEnd
ORDER BY DocDate DESC)
from Table
)
select Id
from prevFilter t
where RN = 1
答案 3 :(得分:0)
您也可以使用:
SELECT *
FROM (
SELECT DISTINCT Sender, Recipient, PeriodStart, PeriodEnd
FROM YourTable t1
) t CROSS APPLY (
SELECT TOP 1 Id
FROM YourTable t2
WHERE t2.Sender = t.Sender
AND t2.Recipient = t.Recipient
AND t2.PeriodStart = t.PeriodStart
AND t2.PeriodEnd = t.PeriodEnd
ORDER BY DocDate DESC
) x
或:
SELECT *
FROM YourTable t1
WHERE NOT EXISTS (
SELECT *
FROM YourTable t2
WHERE t2.Sender = t1.Sender
AND t2.Recipient = t1.Recipient
AND t2.PeriodStart = t1.PeriodStart
AND t2.PeriodEnd = t1.PeriodEnd
AND t2.DocDate>t1.DocDate
)
勒兹