【问题标题】: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

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

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

    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. 这样我们按日期差异排序并获得前 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()。
        猜你喜欢
        • 2022-10-05
        • 1970-01-01
        • 2020-11-20
        • 2014-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-12
        • 1970-01-01
        相关资源
        最近更新 更多