我正在尝试创建一个在 SQLServer 2008 中计算窗口移动平均值的函数。我对SQL很陌生,所以我遇到了一些困难。我尝试执行移动平均线的数据需要按天分组(它是所有带时间戳的数据),然后需要应用可变移动平均窗口。
我已经有了一个按天(和@id)分组数据的功能,它显示在底部。我有几个问题:
在移动平均功能中调用分组功能会更好吗?或者我应该一次性完成所有操作吗?
是否可以获取输入到函数中的日期的移动平均值,但是返回 n 天来开始移动平均线,以便第一个 n 返回数据的天数平均值不为0 (即,如果他们想要从2011年8月1日到2011年8月2日的7天移动平均线,我将在01开始移动平均线计算-01-2011以便他们定义的第一天有值?)
我正在研究如何进行移动平均线,并且知道移动窗口似乎是最好的选择(currentSum = prevSum + todayCount - nthDayAgoCount)/ nDays 但是我我还在努力弄清楚这个的SQL实现。
我有一个看起来像这样的分组函数(为了可见性目的,删除了一些变量):
SELECT
'ALL' as GeogType,
CAST(v.AdmissionOn as date) as dtAdmission,
CASE WHEN @id IS NULL THEN 99 ELSE v.ID END,
COUNT(*) as nVisits
FROM dbo.Table1 v INNER JOIN dbo.Table2 t ON v.FSLDU = t.FSLDU5
WHERE v.AdmissionOn >= '01-01-2010' AND v.AdmissionOn < DATEADD(day,1,'02-01-2010')
AND v.ID = Coalesce(@id,ID)
GROUP BY
CAST(v.AdmissionOn as date),
CASE WHEN @id IS NULL THEN 99 ELSE v.ID END
ORDER BY 2,3,4
返回如下表格:
ALL 2010-01-01 1 103
ALL 2010-01-02 1 114
ALL 2010-01-03 1 86
ALL 2010-01-04 1 88
ALL 2010-01-05 1 84
ALL 2010-01-06 1 87
ALL 2010-01-07 1 82
编辑:要回答我提出的第一个问题:
我最终创建了一个声明临时表并将count函数的结果插入其中的函数,然后使用user662852
中的示例来计算移动平均值。
答案 0 :(得分:2)
从查询中取出硬编码的日期范围。将输出(如最后的样本)写入临时表(我将其称为#visits) 试试这个自我加入临时表:
Select list.dtadmission
, AVG(data.nvisits) as Avg
, SUM(data.nvisits) as sum
, COUNT(data.nvisits) as RollingDayCount
, MIN(data.dtadmission) as Verifymindate
, MAX(data.dtadmission) as Verifymaxdate
from #visits as list
inner join #visits as data
on list.dtadmission between data.dtadmission and DATEADD(DD,6,data.dtadmission) group by list.dtadmission
编辑:我在评论中没有足够的空间来回答您的问题:
我的联接是“有点笛卡尔”,因为它在连接约束中使用了一个。列表中的每个记录都与其他记录相对应,然后我希望我报告的日期介于(-7)天和今天的下限之间。每个数据日期都可用于列出日期,这是您的问题的关键。我本可以将连接条件写为
list.dtadmission between DATEADD(DD,-6,data.dtadmission) and data.dtadmission
但真正发生的事情是我将其作为
进行了测试list.dtadmission between DATEADD(DD,6,data.dtadmission) and data.dtadmission
由于语法为“介于低和高之间”,因此不返回任何记录。我在0条记录上面对并交换了论据,这就是全部。
尝试以下操作,看看我的意思:这只是一个listdate的笛卡尔联接:
SELECT
list.[dtAdmission] as listdate
,data.[dtAdmission] as datadate
,data.nVisits as datadata
,DATEADD(dd,6,list.dtadmission) as listplus6
,DATEADD(dd,6,data.dtAdmission ) as datapplus6
from [sandbox].[dbo].[admAvg] as list inner join [sandbox].[dbo].[admAvg] as data
on
1=1
where list.dtAdmission = '5-Jan-2011'
将此与实际连接条件进行比较
SELECT
list.[dtAdmission] as listdate
,data.[dtAdmission] as datadate
,data.nVisits as datadata
,DATEADD(dd,6,list.dtadmission) as listplus6
,DATEADD(dd,6,data.dtAdmission ) as datapplus6
from [sandbox].[dbo].[admAvg] as list inner join [sandbox].[dbo].[admAvg] as data
on
list.dtadmission between data.dtadmission and DATEADD(DD,6,data.dtadmission)
where list.dtAdmission = '5-Jan-2011'
查看所有记录中datadate和dataplus6之间的列表日期如何?