SQL Hurdle - SQL Server 2008 - PullRequest
       7

SQL Hurdle - SQL Server 2008

2 голосов
/ 10 сентября 2009

Следующий запрос возвращает общее количество заказов в неделю за последние 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 месяцев ... если на этой неделе не существует ордера, то возвращение 0 для orderCount было бы хорошо, но мне все еще нужны год, неделя и месяц. Я, вероятно, могу сделать это, создав отдельную таблицу, в которой хранятся недели года, а затем оставил для нее внешнее объединение, но предпочел бы этого не делать. Возможно, в SQL есть что-то, что может сделать это? Могу ли я создать запрос, используя встроенные функции, чтобы вернуть все недели за последние 12 месяцев со встроенными функциями SQL? Я на SQL Server 2008.

Edit: Используя предложение Скотта, я разместил запрос, решающий эту проблему ниже.

Ответы [ 4 ]

4 голосов
/ 10 сентября 2009

Вы можете присоединиться к рекурсивному 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
2 голосов
/ 10 сентября 2009

Табличный метод, который вы уже знаете, - лучший путь. Мало того, что это дает вам много контроля, но это самая лучшая производительность.

Вы можете написать SQL-код (пользовательскую функцию), чтобы сделать это, но это не будет таким гибким. RDBM предназначены для обработки комплектов.

1 голос
/ 10 сентября 2009

Решение с использованием CTE: (благодаря предложению Скотта)

;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 ... очевидно, неделя может занимать месяцы. .. кто бы знал LOL

0 голосов
/ 10 сентября 2009

В прошлом я делал это с использованием табличного подхода, о котором вы упомянули. Другой способ состоял в том, чтобы создать табличную функцию, в которой я мог бы передавать аргументы для указания начального и конечного диапазона, который я хотел, и он динамически создавал результаты сохранить, добавив таблицу со всеми данными.

...