如何根据表格中的模糊条目获取id

时间:2013-06-07 13:22:32

标签: sql tsql

让我们考虑下表。

Id(PK, int) | DocDate(long) | Sender(varchar) | Recipient(varchar) | PeriodStart(long) | PeriodEnd(long)

对于每个SenderRecipientPerdiodStartPeriodEnd,我正在不同的时间点写入多个条目。所以DocDate不同。

现在,我要选择最新DocDate,foreach SenderRecipientPeriodStartPerdiodEnd的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

您现在可能会认为,此查询的性能很差,但我可以使用聚簇索引来改进它。

但我想知道,如果没有更快更优雅的解决方案来解决这个问题。任何人都可以提供吗?

4 个答案:

答案 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
) 

勒兹