2017-09-01 214 views
1

我想写一个查询(SQL服务器),这将返回每个唯一ID最接近的日期值的完整行。SQL查询返回每个ID最接近的日期匹配

例如,如果有20,000条记录和100个唯一ID,我希望为每个最接近日期值的唯一ID返回100条记录。

的所有数据是在一个单一的表

我已经试过以下不工作

SELECT TOP(1) [Id] 
     ,[Updated] 
     ,[LoadTime] 
     ,[Field4] 
     ,[Field5] 
     ,[Field6] 
    FROM [dbo].[tblTempData] 
WHERE [Updated] <= [LoadTime] 

这只返回1条记录,而不是每个ID一条记录。

SELECT DISTINCT [Id] 
     ,[Updated] 
     ,[LoadTime] 
     ,[Field4] 
     ,[Field5] 
     ,[Field6] 
    FROM [dbo].[tblTempData] 
WHERE [Updated] <= [LoadTime] 

这并不是因为没有其他领域的工作是不同的,所以我得到的多条记录有相同ID

编辑 - 例如数据和输出预计 enter image description here

+0

ID不是唯一订购了一个快捷方式? – phil652

+0

不,Id不是唯一的。 – pathDongle

+1

请显示样本数据和要求的输出。目前尚不清楚哪个日期应该接近哪个日期。 – Serg

回答

1

取决于你“最接近时间”的定义是,这是一种方法,它将为LoadTime和Updated彼此最接近的每个ID返回一条记录,这本质上是第一条更新的记录。

;with cte as(
SELECT [Id] 
     ,[Updated] 
     ,[LoadTime] 
     ,[Field4] 
     ,[Field5] 
     ,[Field6] 
     ,ClosestTime = datediff(second,LoadTime, Updated) 
    FROM [dbo].[tblTempData]), 

select 
    [Id] 
    ,[Updated] 
    ,[LoadTime] 
    ,[Field4] 
    ,[Field5] 
    ,[Field6] 
from 
    cte 
inner join 
    (select Id, min(ClosestTime) dt 
    from cte 
    group by Id) cte2 on cte.Id = cte2.Id and cte2.dt = cte.ClosestTime 

另一种方法是使用row_number()

;with cte as(
SELECT [Id] 
     ,[Updated] 
     ,[LoadTime] 
     ,[Field4] 
     ,[Field5] 
     ,[Field6] 
     ,RN = row_number() over (partition by Id order by LoadTime, Updated) 
FROM [dbo].[tblTempData]) 

select 
    [Id] 
    ,[Updated] 
    ,[LoadTime] 
    ,[Field4] 
    ,[Field5] 
    ,[Field6] 
from 
    cte 
where 
    RN = 1 
+1

谢谢。我选择这个答案的原因是第二个例子是最快的查询。 Serg的回答也非常快(我修改了每个查询,以便返回相同的字段并删除where子句) – pathDongle

+0

row_number()几乎总是比聚合更快:) – scsimon

0

也许最好的方式是先获得与最接近的加载时你正在寻找的记录,然后查询thoose记录(如果你虽然有2条记录与相同的LoadTime和Id,这将产生2个记录为该Id)

SELECT * FROM [dbo].[tblTempData] a 
INNER JOIN (
    SELECT Id,Max(LoadTime) FROM [dbo].[tblTempData] 
    WHERE [Updated]<=[LoadTime] 
    GROUP BY Id,Max(LoadTime)) b 
    ON (a.Id=b.Id AND a.LoadTime=b.LoadTime) 

应该做的工作。

0

怎么样,

SELECT 
    [Id] 
    ,[Updated] 
    ,[LoadTime] 
    ,[Field4] 
    ,[Field5] 
    ,[Field6] 
FROM 
(
    SELECT 
     RANK() OVER (PARTITION BY [Id] ORDER BY DATEDIFF(ms, [Update], [LoadTime] ASC) [R] 
     ,[Id] 
     ,[Updated] 
     ,[LoadTime] 
     ,[Field4] 
     ,[Field5] 
     ,[Field6] 
    FROM 
     [dbo].[tblTempData] 
) O 
WHERE 
    O.[R] = 1; 

注意,那被推迟相同的毫秒数列都将被包括在内。如果你想随机丢弃一个使用ROW_NUMBER()来代替。

1

的SQL服务器具有通过ROW_NUMBER()

SELECT TOP(1) WITH TIES [Id] 
     ,[Updated] 
     ,[LoadTime] 
     ,[Field4] 
     ,[Field5] 
     ,[Field6] 
FROM [dbo].[tblTempData] 
WHERE [Updated] <= [LoadTime] 
ORDER BY row_number() over(PARTITION BY [Id] ORDER BY datediff(second,[Updated],[LoadTime])