tSQL根据日期字段按周汇总数据?

时间:2015-12-28 19:02:13

标签: sql sql-server tsql

我希望按照给定的开始日期到无限期的未来一周汇总数据。通常我只是将结果集转储到Excel短划线并通过枢轴等进行分组,但是我将这个查询写到一组用户并允许他们通过前端BI应用程序进行访问,所以我想尽可能完整地给它们。

我目前的方法显然效率低下,所以我喜欢找到一个简单的公式来做到这一点(或者为本周创建变量以减少所有重复脚本的方法)。我已经考虑过使用DATEADD,但还没有能够让它工作。

我目前的解决方案示例如下:

SELECT 
    'Week Ending' = (CASE 
                        WHEN YEAR(duedate) = '2015' 
                          THEN (CASE 
                                  WHEN datepart(wk, duedate) = 32 THEN '2015/08/07'
                                  WHEN datepart(wk, duedate) = 33 THEN '2015/08/14'
                                  WHEN datepart(wk, duedate) = 34 THEN '2015/08/21'
                                  WHEN datepart(wk, duedate) = 35 THEN '2015/08/28'
                                  WHEN datepart(wk, duedate) = 36 THEN '2015/09/04'
                                  WHEN datepart(wk, duedate) = 37 THEN '2015/09/11'
                                  WHEN datepart(wk, duedate) = 38 THEN '2015/09/18'
                                  WHEN datepart(wk, duedate) = 39 THEN '2015/09/25'
                                  WHEN datepart(wk, duedate) = 40 THEN '2015/10/02'
                                  WHEN datepart(wk, duedate) = 41 THEN '2015/10/09'
                                  WHEN datepart(wk, duedate) = 42 THEN '2015/10/16'
                                  WHEN datepart(wk, duedate) = 43 THEN '2015/10/23'
                                  WHEN datepart(wk, duedate) = 44 THEN '2015/10/30'
                                  WHEN datepart(wk, duedate) = 45 THEN '2015/11/06'
                                  WHEN datepart(wk, duedate) = 46 THEN '2015/11/13'
                                  WHEN datepart(wk, duedate) = 47 THEN '2015/11/20'
                                  WHEN datepart(wk, duedate) = 48 THEN '2015/11/27'
                                  WHEN datepart(wk, duedate) = 49 THEN '2015/12/04'
                                  WHEN datepart(wk, duedate) = 50 THEN '2015/12/11'
                                  WHEN datepart(wk, duedate) = 51 THEN '2015/12/18'
                                  WHEN datepart(wk, duedate) = 52 THEN '2015/12/25'
                                  WHEN datepart(wk, duedate) = 53 THEN '2016/01/01'
                                END)
                        WHEN YEAR(duedate) = '2016' 
                          THEN (CASE 
                                  WHEN datepart(wk, duedate) = 1 THEN '2016/01/01'
                                  WHEN datepart(wk, duedate) = 2 THEN '2016/01/08'
                                  WHEN datepart(wk, duedate) = 3 THEN '2016/01/15'
                                  WHEN datepart(wk, duedate) = 4 THEN '2016/01/22'
                                END)
                     END),
    SUM(linetotal) 
FROM 
    PurchaseOrderDetail
WHERE 
    YEAR(duedate) > '2014'
GROUP BY 
    YEAR(duedate), DATEPART(wk, duedate)

我想答案很简单,但我还没有找到我想要的东西。

3 个答案:

答案 0 :(得分:0)

考虑这些方面的解决方案(请注意 - 代码未经测试,因为我现在无法访问SQL Server实例)。这个想法是用年份和周数代替(硬编码)日期。此建议的解决方案将允许BI用户按年份和周编号查看linetotal的SUM。随着您获得更多数据,用户甚至可以比较每周linetotal每年(linetotal 2014年,2015年,2016年......)。

SELECT
    YEAR(duedate) AS Year1, datepart(wk, duedate), SUM(linetotal)
FROM 
    PurchaseOrderDetail
WHERE 
    YEAR(duedate) > '2014'
GROUP BY 
    YEAR(duedate), DATEPART(wk, duedate)

答案 1 :(得分:0)

这样的东西可以为您提供相同的输出,而无需手动指定每周结束日期:

SELECT
convert(varchar, duedate - datepart(dw, duedate) + 6, 111) as [Week Ending],
sum(linetotal) 

FROM 
PurchaseOrderDetail

WHERE 
year(duedate) > '2014'

GROUP BY 
year(duedate), convert(varchar, duedate - datepart(dw, duedate) + 6, 111)

转换为varchar(样式111)并非绝对必要,但它会提供相同的' YYYY / MM / DD'您原始案例陈述中的格式。你可以很容易地使用duedate - datepart(dw, duedate) + 6而没有转换函数,转换函数将输出相同的值,但使用相同的datetime / datetime2 / smalldatetime格式作为输入(可能' YYYY-MM-DD HH:MM :SS&#39)

答案 2 :(得分:0)

您正在寻找的功能可能是:

SELECT 
    'Week Ending' = dateadd( wk,
                             datepart(wk,duedate)-1, 
                             DATEADD(DAY, 
                                     6 - DATEPART(WEEKDAY, DATEADD(YEAR, year(duedate) - 1900, 0)), 
                                     DATEADD(YEAR, year(duedate) - 1900, 0)))