SQL 问题 - 如何在 SQL 服务器中使用迭代日期逻辑输出

SQL question - how to output using iterative date logic in SQL Server

我有以下示例 table(为简单起见提供了单个 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

这是我需要的示例输出

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

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

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

  4. 如果后续日期超过上次新访问的 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

您需要一个递归 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;

您需要对此进行递归查询。

您将枚举行,然后按日期升序遍历数据集,同时跟踪每个组的首次访问日期;当距离上次首次访问的时间间隔超过 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)