SQL Hurdle - SQL Server 2008

时间:2009-09-10 16:33:04

标签: sql sql-server datetime date

以下查询返回过去12个月(针对特定客户)的每周订单总数:

SELECT DATEPART(year, orderDate) AS [year],
       DATEPART(month, orderDate) AS [month],
       DATEPART(wk, orderDate) AS [week],
       COUNT(1) AS orderCount
FROM dbo.Orders (NOLOCK)
WHERE customerNumber = @custnum
AND orderDate >= DATEADD(month, -12, GETDATE())
GROUP BY DATEPART(year, orderDate),
         DATEPART(wk, orderDate),
         DATEPART(month, orderDate)
ORDER BY DATEPART(year, orderDate),
         DATEPART(wk, orderDate)

这会返回如下结果:

year    month    week    orderCount
2008      1        1         23
2008      3        12        5

...

正如您所看到的,结果集中只返回有此客户订单的周数。我需要它在过去12个月内每周返回一行......如果本周没有订单,那么为orderCount返回0会没事,但我仍然需要年,周和月。我可以通过创建一个存储一年中几周的单独表来完成它,然后将外部联接对抗它,但不愿意。也许在SQL中可以实现这一点?我是否可以使用内置函数创建查询,以使用内置SQL函数返回过去12个月中的所有周?我在SQL Server 2008上。

修改 使用Scott的建议我在下面发布了解决此问题的查询。

4 个答案:

答案 0 :(得分:4)

你可以加入一个递归的CTE - 像下面这样的东西应该给你一个开始......

WITH MyCte AS    
    (SELECT MyWeek = 1     
    UNION ALL     
    SELECT  MyWeek + 1     
    FROM    MyCte     
    WHERE   MyWeek < 53)
SELECT  MyWeek, 
        DATEPART(year, DATEADD(wk, -MyWeek, GETDATE())),
        DATEPART(month, DATEADD(wk, -MyWeek, GETDATE())),
        DATEPART(wk, DATEADD(wk, -MyWeek, GETDATE()))
FROM    MyCte

答案 1 :(得分:2)

您已经知道的表方法是最好的方法。它不仅为您提供了很多控制权,而且表现最佳。

您可以编写sql代码(用户函数)来执行此操作,但它不会那么灵活。 RDBM用于处理集合。

答案 2 :(得分:1)

使用CTE的解决方案:(感谢Scott的建议)

;WITH MyCte AS    
    (SELECT     MyWeek = 1     
    UNION ALL     
    SELECT      MyWeek + 1     
    FROM        MyCte     
    WHERE       MyWeek < 53)

SELECT  myc.[year],
        myc.[month],
        myc.[week],
        isnull(t.orderCount,0) AS orderCount,
        isnull(t.orderTotal,0) AS orderTotal
FROM (SELECT  MyWeek, 
        DATEPART(year, DATEADD(wk, -MyWeek, GETDATE())) AS [year],
        DATEPART(month, DATEADD(wk, -MyWeek, GETDATE())) AS [month],
        DATEPART(wk, DATEADD(wk, -MyWeek, GETDATE())) AS [week]
        FROM    MyCte) myc

        LEFT OUTER JOIN 

        (SELECT DATEPART(year, orderDate) AS [year],
               DATEPART(month, orderDate) AS [month],
               DATEPART(wk, orderDate) AS [week],
               COUNT(1) AS orderCount,
               SUM(orderTotal) AS orderTotal
        FROM dbo.Orders (NOLOCK)
        WHERE customerID = @custnum
        AND orderDate >= DATEADD(month, -12, GETDATE())
        GROUP BY DATEPART(year, ODR_DATE),
                 DATEPART(wk, orderDate),
                 DATEPART(month, orderDate)) t ON t.[year] = myc.[year] AND t.[week] = myc.[week]
ORDER BY myc.[year],
         myc.[week]

编辑:只是注意到一周是重复的(同一周有2个记录)...可能是一个简单的逻辑错误......无视...... ID-10-T ......显然一周可以跨越几个月。 ..谁会知道大声笑

答案 3 :(得分:0)

过去我使用你提到的表方法完成了这个,另一种方法是创建一个表函数,我可以传递参数来指定我想要的开始和结束范围,它会动态地构建结果保存需要添加包含所有数据的表。