0

我有一张桌子叫patients. 我正在尝试查询每月平均每日患者。例如,如果我今天查询:

select count(*) from patients where active=1

它返回:

-----------
213

(1 row(s) affected)

从数学上讲,我需要计算每天的计数,然后除以该月的天数。

如果我想获得每月活跃患者的平均每日人数,我该怎么做?

编辑:

Patient ID一些显示 a和它们的示例数据creation_date

Patient ID  creation_date
----------- -----------------------
48          2011-11-16 08:59:34.000
55          2011-11-16 09:09:20.000
82          2011-11-16 09:32:48.000
110         2011-11-16 09:42:38.000
111         2011-11-16 09:42:53.000
123         2011-11-16 09:47:01.000
138         2011-11-16 09:58:02.000
188         2011-11-16 10:20:03.000
225         2011-11-16 10:32:53.000
231         2011-11-16 10:34:48.000
241         2011-11-16 10:38:13.000
259         2011-11-16 10:44:35.000
377         2011-12-17 10:26:21.000
536         2012-02-02 16:10:57.000
551         2012-02-05 11:42:22.000
591         2012-02-12 12:14:57.000

我想要的结果是这样的:

Month                          Month Number Year        ADP
------------------------------ ------------ ----------- -----------
November                       11           2011        240
December                       12           2011        280
January                        1            2012        220
February                       2            2012        225
March                          3            2012        241
April                          4            2012        212
May                            5            2012        210

编辑:似乎提交的答案给了我新患者的平均每日计数,这是一个较小的数字。我需要总人口的平均每日计数。

编辑:我了解到患者状态跟踪是在一个名为的表中跟踪的,该表patient_booking_data的列名为release. 这可能会有所帮助。以下是该表中的示例数据:

id          pid         booking_no                       date                    release                 active facility date_created            temporary temporary_no
----------- ----------- -------------------------------- ----------------------- ----------------------- ------ -------- ----------------------- --------- --------------------------------
1           1           12345                            2011-11-03 00:00:00.000 2011-11-15 10:45:00.000 0      11535    2011-11-03 12:45:36.000 0         NULL
2           2           7890                             2011-11-14 12:00:00.000 2011-11-21 07:01:00.000 1      11535    2011-11-14 08:45:33.000 0         NULL
3           3           100                              2011-11-14 09:00:00.000 2011-11-21 07:00:00.000 1      11535    2011-11-14 08:45:34.000 0         NULL
4           4           111                              2011-11-14 09:00:00.000 2011-11-21 07:01:00.000 1      11535    2011-11-14 08:45:34.000 0         NULL
5           5           12                               2011-11-14 10:20:00.000 2011-11-21 07:02:00.000 1      11535    2011-11-14 10:21:25.000 0         NULL
6           6           1234                             2011-11-14 00:00:00.000 2011-11-21 07:02:00.000 1      11535    2011-11-14 10:25:10.000 0         NULL
7           7           1123                             2011-11-14 11:14:00.000 2011-11-21 07:01:00.000 1      11535    2011-11-14 11:15:44.000 0         NULL
4

5 回答 5

2
SELECT  m,
        cnt * 1. / DATEDIFF(day, m, DATEADD(month, 1, m)) AS adp
FROM    (
        SELECT  DATEADD(month, DATEDIFF(month, 0, creation_date), 0) AS m, COUNT(*) AS cnt
        FROM    mytable
        GROUP BY
                DATEADD(month, DATEDIFF(month, 0, creation_date), 0)
        ) q

更新:

创建一个表来跟踪患者状态的变化:

CREATE TABLE
        status
        (
        id INT NOT NULL PRIMARY KEY,
        patient INT NOT NULL,
        active BIT NOT NULL,
        ts DATETIME NOT NULL
        )

CREATE INDEX
        ix_status_patient_ts
ON      status (patient, ts) INCLUDE (active)

并记录患者的每个状态变化。

然后运行这个查询:

WITH    months (mon) AS
        (
        SELECT  '2012-01-01'
        UNION ALL
        SELECT  DATEADD(month, 1, mon)
        FROM    months
        WHERE   m < '2014-12-01'
        )
SELECT  mon, COUNT(*)
FROM    patient p
CROSS JOIN
        months m
CROSS APPLY
        (
        SELECT  TOP 1
                active
        FROM    status s
        WHERE   s.patient = p.id
                AND s.ts <= m.mon
        ORDER BY
                ts DESC, id DESC
        ) s
WHERE   s.active = 1
GROUP BY
        mon
于 2013-04-03T13:05:58.297 回答
0

可能是我写过的最不优雅的查询,但它确实给了你想要的结果,即每月每天的平均患者数:

SELECT DATENAME(MONTH, creation_date) AS [Month],
       DATEPART(MONTH, creation_date) AS [Month Number],
       DATEPART(YEAR, creation_date) AS Year,
       CAST(COUNT(*) AS FLOAT) / DATEDIFF(DAY, DATEADD(DAY, 1 - DAY(creation_date), creation_date), DATEADD(MONTH, 1, DATEADD(DAY, 1 - DAY(creation_date), creation_date))) AS ADP
  FROM patients
  GROUP BY DATENAME(MONTH, creation_date),
       DATEPART(month, creation_date),
       DATEPART(year, creation_date),
       DATEDIFF(DAY, DATEADD(DAY, 1 - DAY(creation_date), creation_date), DATEADD(MONTH, 1, DATEADD(DAY, 1 - DAY(creation_date), creation_date)))
  ORDER BY 3, 2

这是在SQLFiddle上。

于 2013-04-03T13:08:15.620 回答
0

这似乎回答了你的问题:

SELECT YEAR(thedate), MONTH(thedate), datename(month, thedate()), AVG(cnt*1.0)
FROM (SELECT cast(creation_date as date) as thedate, count(*)  as cnt
      FROM patients
      where active = 1
      GROUP BY cast(creation_date as date)
     ) t
group by YEAR(thedate), MONTH(thedate),  datename(month, thedate())
order by 1, 2;

这个 versino 假设您每天都有数据。仔细查看您的数据表明情况并非如此,这个版本很接近:

SELECT YEAR(thedate), MONTH(thedate), datename(month, thedate()),
        sum(cnt*1.0) / count(*) as average
FROM (SELECT cast(creation_date as date) as thedate, count(*)  as cnt
      FROM patients
      where active = 1
      GROUP BY cast(creation_date as date)
     ) t
group by YEAR(thedate), MONTH(thedate),  datename(month, thedate())
order by 1, 2;

如果您真的想计算天数,并且没有日历表,那么 SQL 会变得更复杂一些。以下假设您每个月至少有一条记录(以生成 mons 表):

with pc as (
      SELECT cast(creation_date as date) as thedate, count(*)  as cnt,
             MIN(YEAR(creation_date)*12+MONTH(creation_date)) as monnum
      FROM patients
      where active = 1
      GROUP BY cast(creation_date as date)
     ),
     mons as (
      select distinct YEAR(creation_date) as yr, MONTH(creation_date) as mon, DATENAME(month, creation_date) as monname,
             CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(creation_date)-1),creation_date),101) as FirstDay,
             CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,creation_date))),DATEADD(mm,1,creation_date)),101) as LastDay,
             YEAR(creation_date)*12+MONTH(creation_date) as monnum
      from patients
     )
SELECT mons.yr, mons.mon, mons.monname,
       (SUM(datediff(day, (case when pc.thedate < mons.FirstDay then mons.FirstDay else  pc.thedate end),
                     (case when pc.thedate > mons.LastDay then mons.LastDay else pc.thedate end)
                    ) * pc.cnt
           ) /
        SUM(datediff(day, (case when pc.thedate < mons.FirstDay then mons.FirstDay else  pc.thedate end),
                     (case when pc.thedate > mons.LastDay then mons.LastDay else pc.thedate end)
                    )
           )
       ) as avgday
FROM mons join
    (select pc.*,
             (select top 1 pc2.monnum from pc pc2 where pc2.thedate > pc.thedate order by thedate
             ) as nextmonnum
      from pc
     ) pc
     on mons.monnum between pc.monnum and pc.nextmonnum
group by mons.yr, mons.mon, mons.monname
order by 1, 2;

基本上,它为每个病人记录创建一个开始和结束日期——由于没有新病人进来,计数将保持不变的时间段。然后它会做一堆摆弄和算术来计算病人天数每个月和每个月的天数。我没有对此进行测试,因此它很容易受到语法错误和非一错误的影响。我在这里举个例子。

但是,您计算的是过去几个月当前活跃的患者数量,而不是那些月份的活跃患者数量。

要获取活动患者的数量,您需要提供“激活”和“停用”的日期。

于 2013-04-03T13:08:17.713 回答
0

试试这个代码:

    select  to_char(creation_date, 'mon') Month,
            to_char(creation_date, 'mm') Month_Number,
            to_char(creation_date, 'yyyy') Year,
            count(Patient_ID) / to_char(last_day(to_date(to_char(creation_date, 'yyyymm')),'DD') Avg_per_Month
       from patients 
      where active=1
   group by to_char(creation_date, 'mon'),
            to_char(creation_date, 'mm'),
            to_char(creation_date, 'yyyy'),
            to_char(last_day(to_date(to_char(creation_date, 'yyyymm')),'DD')

以下代码返回给定月份的天数:

to_char(last_day(to_date(to_char(creation_date, 'yyyymm')),'DD')
于 2013-04-03T13:09:21.733 回答
0

您可以通过以下方式确定一个月的第一天:

dateadd(month, datediff(month, 0, @date), 0)

下个月的第一天:

dateadd(month, 1 + datediff(month, 0, @date), 0)

一个月的天数就是两者之差。应用于您的问题,这将变为:

select  datepart(year, creation_date) as Year
,       datepart(month, creation_date) as Month
,       1.0 * count(*) / datediff(day,
            dateadd(month, datediff(month, 0, min(creation_date)), 0),
            dateadd(month, 1+datediff(month, 0, min(creation_date)), 0))
            as DailyAverage
from    Table1
group by
        datepart(year, creation_date)
,       datepart(month, creation_date)

SQL Fiddle 的示例。

于 2013-04-03T13:14:27.127 回答