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?
SQL 问题 - 如何在 SQL Server 中使用迭代日期逻辑进行输出