Sql 使用声明性查询进行每日普查
给定如下所示的数据集:Sql 使用声明性查询进行每日普查,sql,sql-server,Sql,Sql Server,给定如下所示的数据集: ID admission_date discharge_date 1 2016-02-27 2016-05-06 2 2016-03-06 2016-05-13 3 2016-03-14 2016-05-03 4 2016-04-01 2016-05-19 5 2016-04-03 2016-06-15 6 2016-04-06 2016-05-14 7 2016-04-27
ID admission_date discharge_date
1 2016-02-27 2016-05-06
2 2016-03-06 2016-05-13
3 2016-03-14 2016-05-03
4 2016-04-01 2016-05-19
5 2016-04-03 2016-06-15
6 2016-04-06 2016-05-14
7 2016-04-27 2016-05-03
8 2016-04-27 2016-05-10
9 2016-04-28 2016-05-04
10 2016-04-28 2016-05-01
11 2016-04-28 2016-05-14
12 2016-04-29 2016-05-02
13 2016-04-29 2016-05-01
我想统计每一行的行数,即在给定范围内进行每日普查。对于从“2016-05-01”到“2016-05-02”的每日人口普查,预期结果为:
date census
2016-05-01 13
2016-05-02 11 (rows 10 and 13 do not count because patient
was not hospitalized on 2016-05-02)
我正在努力找到一种方法来正确统计所有日子的人口普查数据。有一段时间我一直在使用窗口函数,但我想不出一种排除行的方法来实现上述结果。目前我正试图通过使用游标来解决这个问题
所以问题是:是否可以使用纯声明性SQL查询来实现这一点
为了说明人们对人口普查的看法,讨论了一个几乎相同的想法,但主要的区别在于,在这里讨论的方法假设,2016-05-01,你将不计算在2016-05-01出院的病人,这个想法是让你每天用窗函数总结的。这将使2016-05-01年的上述总数减少到11
如果您有日期表,这是可能的。如果没有,您可以使用递归cte生成它们,并将其用于查询--Use the recursive cte only if there isn't a dates table in the database
--Generates all dates in 2016
with dates(dt) as (select cast('2016-01-01' as date)
union all
select dateadd(day,1,dt)
from dates
where dt<'2017-01-01'
)
--Actual query
select d.dt,count(distinct t.id)
from tbl t
join dates d on d.dt>=t.admission_date and d.dt<=t.dishcarge_date
where d.dt>='2016-05-01' and d.dt<='2016-05-02' --change this as needed
group by d.dt
option (maxrecursion 0)
如果您有日期表,这是可能的。如果没有,您可以使用递归cte生成它们,并将其用于查询
--Use the recursive cte only if there isn't a dates table in the database
--Generates all dates in 2016
with dates(dt) as (select cast('2016-01-01' as date)
union all
select dateadd(day,1,dt)
from dates
where dt<'2017-01-01'
)
--Actual query
select d.dt,count(distinct t.id)
from tbl t
join dates d on d.dt>=t.admission_date and d.dt<=t.dishcarge_date
where d.dt>='2016-05-01' and d.dt<='2016-05-02' --change this as needed
group by d.dt
option (maxrecursion 0)
以下是一种仅在您列出的日期提供普查的方法:
with d as (
select v.*
from t cross apply
(values (admission_date, 1, 0),
(discharge_date, 0, 1)
) v(dte, incoming, outgoing)
)
select dte,
(sum(sum(incoming)) over (order by dte) - sum(sum(outgoing)) over (order by dte)
) as census
from d
group by dte
order by dte;
这可能是最快的方法。如果您有日历表或希望使用递归CTE,则可以将其扩展到所有日期。这里有一种方法仅提供您列出的日期的普查:
with d as (
select v.*
from t cross apply
(values (admission_date, 1, 0),
(discharge_date, 0, 1)
) v(dte, incoming, outgoing)
)
select dte,
(sum(sum(incoming)) over (order by dte) - sum(sum(outgoing)) over (order by dte)
) as census
from d
group by dte
order by dte;
这可能是最快的方法。如果您有日历表或希望使用递归CTE,则可以将其扩展到所有日期。这实际上解决了我在问题最后一段中描述的场景,但实际上我也有一个用于此的用例,并且比我当前使用的要短得多,因此感谢!编辑:我不得不说,我需要盯着它来解析它,但我可以从运行查询中看到,它确实为我获得了正确的数据!这实际上解决了我在问题的最后一段中描述的场景,但实际上我也有一个用于此的用例,它比我当前使用的要短得多,因此感谢!编辑:我不得不说,我需要盯着它来解析它,但我可以从运行查询中看到,它确实为我获得了正确的数据!