2017-09-01 212 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])