我有一张名为patients
的表格。我正在尝试查询每月平均每日患者。例如,如果我今天查询:
select count(*) from patients where active=1
它返回:
-----------
213
(1 row(s) affected)
在数学上,我需要每天计算,然后除以当月的天数。
如果我想获得每月活跃患者的平均每日计数,我该怎么做?
编辑:
一些示例数据显示Patient ID
及其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
编辑:似乎提交的答案给了我新患者的平均每日计数,这是一个较小的数字。我需要TOTAL人口的平均每日计数。
编辑:我了解到患者状态跟踪会在名为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
答案 0 :(得分: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
答案 1 :(得分: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。
答案 2 :(得分: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;
这个版本假设您每天都有数据。仔细看看你的数据表明情况并非如此,这个版本接近:
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;
基本上,它会为每个患者记录创建一个开始日期和结束日期 - 计数将保持不变的时间段,因为没有新患者进入。然后它会进行一系列摆弄和算术来计算每个患者的数量。每月患者天数和每月的天数。我没有对此进行测试,因此很容易出现语法错误和逐个错误。我在这里举一个例子。
然而,您所依据的是过去几个月当前活跃的患者数量,而不是那几个月活跃患者的数量。
要获得活跃患者的数量,您需要提供“激活”和“停用”的日期。
答案 3 :(得分: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')
答案 4 :(得分: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)