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 中使用迭代日期逻辑进行输出的主要内容,如果未能解决你的问题,请参考以下文章

如何在 AG Listener SQL Server 中添加数据库,并在主 SQL Server 和辅助 SQL Server 上创建?

如何在 SQL Server 中连接两个 SQL 查询?

如何在 SQL Server 中清理(防止 SQL 注入)动态 SQL?

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

如何在 sql server 2005 中编写 sql server 数据库图表脚本?

如何解决sql server18456错误