2011-03-23 51 views
1

我正在尝试创建一个函数,该函数计算SQL Server 2008中的窗口移动平均值。我对SQL很陌生,所以我遇到了一些困难。我试图执行移动平均的数据需要按日进行分组(这是所有时间戳数据),然后需要应用可变移动平均窗口。SQL Server中的窗口移动平均值

我已经有一个函数按日期分组数据(和@id),它显示在底部。我有几个问题:

在移动平均函数内部调用分组函数还是应该一次完成所有操作?

是否有可能得到该输入日期,该函数的移动平均线,但回去ň天开始移动平均线,以便返回数据的第一ñ天不会有0他们的平均水平?(即如果他们想要从2011年8月1日至2011年2月8日的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 

编辑:要回答我问的第一个问题:

我最终创建了一个函数,它声明了一个临时表并将结果从t他将功能计入其中,然后使用user662852中的示例来计算移动平均值。

回答

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 

编辑:我没有足够的空间在评论中针对您的问题可以说了:

我的连接是“有点笛卡尔“因为它在连接约束中使用了一个between。列表中的每条记录都与其他记录相对应,然后我希望那些我报告的日期介于(-7)天到今天的下限之间的记录。每个数据日期都可以列出日期,这是你的问题的关键。我可以写连接条件为

list.dtadmission between DATEADD(DD,-6,data.dtadmission) and data.dtadmission 

但真正的情况是我测试了它作为

list.dtadmission between DATEADD(DD,6,data.dtadmission) and data.dtadmission 

因为语法是“LOW和HIGH之间”不返回任何记录。我记录在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的所有记录?

+0

对不起,硬编码日期范围以及查询中的其他一些事情只是为了给出它的一个想法/用于测试目的,而实际函数具有这些变量。不过我会试试这个! – Mike 2011-03-23 15:47:45

+0

你能向我解释这是6天前加上当天的情况吗?我知道它确实这样做,但是当我看到它时,由于DATEADD功能,我将其视为加6天 – Mike 2011-03-23 19:32:16

+1

我编辑了回答您的问题的答案 – user662852 2011-03-23 20:56:26