SQL 问题 - 如何在 SQL Server 中使用迭代日期逻辑进行输出

Posted

技术标签:

【中文标题】SQL 问题 - 如何在 SQL Server 中使用迭代日期逻辑进行输出【英文标题】:SQL question - how to output using iterative date logic in SQL Server 【发布时间】:2020-09-07 16:32:36 【问题描述】:

我有以下示例表(为简单起见提供了单个 ID - 需要对所有 ID 执行相同的逻辑)

ID    Visit_date
-----------------
ABC   8/7/2019
ABC   9/10/2019
ABC   9/12/2019
ABC   10/1/2019
ABC   10/1/2019
ABC   10/8/2019
ABC   10/15/2019
ABC   10/17/2019
ABC   10/24/2019

这是我获取示例输出所需的内容

    在“new_visit”列中将第一次访问标记为 1

    将后续日期与第一个日期进行比较,直到超过 21 天的条件。示例 9 月 10 日与 8 月 7 日相比,它不在 8 月 7 日之后的 21 天内,因此这被视为另一个 new_visit,因此将 new_visit 标记为 1

    然后,我们将 9 月 10 日与具有 21 天标准的后续日期进行比较,并将所有这些日期标记为 9 月 10 日访问的后续日期。例如。 9 月 12 日、10 月 1 日为 9 月 10 日后的 21 天内;因此它们被视为后续访问,因此将“follow_up”标记为 1

    如果后续日期超过上一次新访问的 21 天标准(例如 10 月 8 日与 9 月 10 日相比),则 10 月 8 日将被视为新访问并将“New_visit”标记为 1,随后的日期将与 10 月进行比较8

样本输出:

Dates   New_Visit   Follow_up
-----------------------------
8/7/2019    1   
9/10/2019   1   
9/12/2019               1
10/1/2019               1
10/1/2019               1
10/8/2019   1   
10/15/2019              1
10/17/2019              1
10/24/2019              1

【问题讨论】:

请使用适当的数据库平台编辑问题和标签。谢谢 那么,您的意思是,如果有人在 22 天内每天都访问,那么第 22 天将是“新”访问? 另外,有用的提示,请不要使用 M/d/yyyy 的格式作为日期;这使得使用数据变得非常困难。 请试一试,向我们展示您的尝试。 这个问题已经回答了。非常感谢 GMB 和 Gordon! 【参考方案1】:

你需要一个递归查询。

您将枚举行,然后按升序遍历数据集,同时跟踪每个组的首次访问日期;当自上次第一次访问以来的间隔超过 21 天时,第一次访问的日期将重置,并开始一个新的组。

with 
    data as (
        select t.*, row_number() over(partition by id order by date) rn 
        from mtytable t
    ),
    cte as (
        select id, visit_date, visit_date first_visit_date
        from data
        where rn = 1
        union all
        select c.id, d.visit_date, case when d.visit_date > datead(day, 21, c.first_visit_date) then d.visit_date else c.first_visit_date end
        from cte c
        inner join data d on d.id = c.id and d.rn = c.rn + 1
    )
select
    id,
    date,
    case when visit_date = first_visit_date then 1 else 0 end as is_new
    case when visit_date = first_visit_date then 0 else 1 end as is_follow_up
from cte

如果患者的就诊次数可能超过 100 次,那么您需要在查询的最后添加 option (maxrecursion 0)

【讨论】:

这太棒了!!非常感谢!【参考方案2】:

您需要一个递归 CTE 来处理这个问题。这就是想法,尽管确切的语法可能因数据库而异:

with recursive t as (
      select id, date,
             row_number() over (partition by id order by date) as seqnum
      from yourtable
     ),
     recursive cte as (
      select id, date, visit_start as date, 1 as is_new_visit
      from t
      where id = 1
      union all
      select cte.id, t.date, 
             (case when t.date < visit_start + interval '21 day'
                   then cte.visit_start else t.date
              end) as visit_start,
             (case when t.date < cte.visit_start + interval '21 say'
                   then 0 else 1
              end) as is_new_visit
      from cte join
           t
           on t.id = cte.id and t.seqnum = cte.seqnum + 1
     )
select *
from cte
where is_new_visit = 1;

【讨论】:

谢谢戈登!!我从你的回复中得到了这个想法。但是,我使用了 GMB 共享的查询,因为它在语法上更接近我正在使用的平台。但是,它基于您共享的相同原理/逻辑。谢谢!! @Somy 。 . .如果你正确地标记了你的问题,你会更快得到答案。 当然学到了!!不过话虽如此,我在几分钟内就得到了答案,太好了!!

以上是关于SQL 问题 - 如何在 SQL Server 中使用迭代日期逻辑进行输出的主要内容,如果未能解决你的问题,请参考以下文章