仅返回一列中的日期与另一列中的日期最接近的行?

Posted

技术标签:

【中文标题】仅返回一列中的日期与另一列中的日期最接近的行?【英文标题】:Return only the row where the date in one column is closest to the date in another column? 【发布时间】:2021-06-04 19:54:29 【问题描述】:

我正在处理一个查询,但它返回了一些重复的值,我只需要返回一列中的日期与另一列中的日期最接近的行。

我的查询如下所示:

SELECT p.Id, r.ReferralDate, s.SupervisionDate
FROM person p
INNER JOIN referral r on r.PersonId = p.Id 
INNER JOIN supervision s on s.PersonId = p.Id

返回如下内容:

Id Supervision Date Referral Date
123 2015-09-30 2015-08-30
123 2020-02-30 2015-08-30
123 2020-06-30 2015-08-30
456 2010-06-30 2010-07-30
456 2005-06-30 2010-07-30

如何编写一个查询来返回最接近推荐日期的监督日期?这样最终的输出看起来像这样:

Id Supervision Date Referral Date
123 2015-09-30 2015-08-30
456 2010-06-30 2010-07-30

【问题讨论】:

【参考方案1】:

在这种情况下,您可以使用两种方式来选择您需要的记录。

    我更喜欢这种方式,因为它是非常有效的解决方案。我们按日期差异获取行顺序并选择最小日期差异。第一种方式,您可以选择要显示的列。这也是更通用的解决方案。

    SELECT  A.Id
     , A.ReferalDate
     , A.Supervision 
    
    FROM 
    (
    
     SELECT 
       p.Id
       , r.ReferalDate
       , s.Supervision   
       ,ROW_NUMBER() OVER (PARTITION BY p.Id ORDER BY  DATEDIFF(DD,r.ReferalDate,s.Supervision) ASC) as [row_num]
      FROM person p
         INNER JOIN referral r 
            on r.pid = p.Id 
         INNER JOIN supervision s 
           on s.pid = p.Id
     ) AS A 
    WHERE A.row_num = 1
    

    这样我们按日期差异排序并获得前 1 条记录。如果将此添加到 CTE 或派生表中,您仍然可以只返回您需要的列。此查询是特定于场景的,因为我们不考虑分区。

    SELECT top 1
        p.Id
       , r.ReferalDate
       , s.Supervision   
       ,DATEDIFF(DD,r.ReferalDate,s.Supervision) as [date dif]
    FROM person p
    INNER JOIN referral r 
        on r.pid = p.Id 
    INNER JOIN supervision s 
        on s.pid = p.Id
    ORDER BY [date dif] ASC
    

两种方式都返回相同的结果,因为我们的订单是在日期差异上下达的。

【讨论】:

【参考方案2】:

这是一种方法:

select p.Id, r.ReferralDate, s.SupervisionDate from (
 select p.Id, r.ReferralDate, s.SupervisionDate , row_number() over (partition by id order by abs(datediff(day , ReferralDate,SupervisionDate))) rn
 from person p
 join referral r on r.PersonId = p.Id 
 join supervision s on s.PersonId = p.Id
) t
where rn = 1

【讨论】:

【参考方案3】:

另一种方式:

select ID, SUP from 
( SELECT 
   p.Id 'ID', 
   r.ReferralDate 'REF', 
   s.SupervisionDate 'SUP',
   min(julianday(s.SupervisionDate) - julianday(r.ReferralDate) ) 'diff'

FROM person p
INNER JOIN referral r on r.PersonId = p.Id 
INNER JOIN supervision s on s.PersonId = p.Id

GROUP BY p.ID
)

这将根据要求返回 ID 和 SupervisionDate。

【讨论】:

除非我很困惑,否则这将总共返回 1 行,而不是每个 id 1 行。 @Andrew 你是绝对正确的,发帖人的例子只使用了 ID 123,所以我没有考虑到会有其他 ID。帖子会更新的,我的错。显示良好的采样日期有多重要。 有没有 julianday() 的替代方法?它在 SQL Server 中不起作用。 @JLo,抱歉,将您的问题读为 SQLite。对于 MSSQL,我相信您可以使用 DATEDIFF(day, firstdate, seconddate) 而不是朱利安日期之间的差异。然后只需选择其中的最小值。 这个答案使用的是 SQLLIte 中的一些函数 julianday()。

以上是关于仅返回一列中的日期与另一列中的日期最接近的行?的主要内容,如果未能解决你的问题,请参考以下文章

在另一列满足条件后计算一列中的值

如何根据Python中另一列中的日期查找最频繁的值

如何在 Presto 中获取连续日期,其中一列中的开始日期和另一列中的结束日期

返回与另一列中的最小值匹配的 ID 行 [重复]

在python中,我如何对一列中每个值与另一列中的值发生的次数(多少行)建立矩阵?

返回值的公式,其中一列中的第一个单词与另一列的最后四位匹配