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,则可以将其扩展到所有日期。

这实际上解决了我在问题最后一段中描述的场景,但实际上我也有一个用于此的用例,并且比我当前使用的要短得多,因此感谢!编辑:我不得不说,我需要盯着它来解析它,但我可以从运行查询中看到,它确实为我获得了正确的数据!这实际上解决了我在问题的最后一段中描述的场景,但实际上我也有一个用于此的用例,它比我当前使用的要短得多,因此感谢!编辑:我不得不说,我需要盯着它来解析它,但我可以从运行查询中看到,它确实为我获得了正确的数据!