Отображение одной строки для каждой календарной недели в SQL - PullRequest
1 голос
/ 27 сентября 2011

У меня есть SQL-запрос, который извлекает единицу продаж по элементам за неделю:

SELECT sls_vendor, 
   sls_item, 
   sls_units, 
   DATEPART(week, sls_week) AS sls_date 
FROM   mytable 

Предположим, я смотрю на 8-недельный период, но не каждая комбинация предмет / продавец имеет полные 8 недель продаж. Однако мне нужно, чтобы мой запрос показывал нулевое значение в этом экземпляре. Таким образом, запрос будет возвращать 8 строк для каждой комбинации товара / поставщика независимо от наличия.

Я попытался создать временную таблицу с номерами от 28 до 35 и выполнить левое соединение в приведенном выше запросе, но при этом не отображаются нулевые значения. Результаты ничем не отличаются от запуска только исходного запроса.

Я могу думать о том, как это сделать, используя перекрестный запрос / сводный запрос, но разве это не то, что должно делать соединение?

Изменить: Обновлено, чтобы показать мой запрос на присоединение. Datetable имеет только 8 строк с 1 добавочным номером для каждой календарной недели.

SELECT * FROM @datetable
    LEFT JOIN
    (SELECT 
        sls_vendor,
        sls_item,
        sls_units,
        datepart(week,sls_week) AS sls_date
    FROM mytable) AS QRY
    ON temp_week = qry.sls_date

Ответы [ 3 ]

0 голосов
/ 27 сентября 2011

Ваш метод должен работать просто отлично:

;with mytable as (
    select 1 as sls_vendor, 'Test' as sls_item, 30 as sls_units, '8/7/2011' as sls_week union
    select 1 as sls_vendor, 'Test' as sls_item, 30 as sls_units, '8/14/2011' as sls_week union
    select 1 as sls_vendor, 'Test' as sls_item, 30 as sls_units, '8/21/2011' as sls_week
)
,datetable as (
    select 28 as temp_week union
    select 29 union
    select 30 union
    select 31 union
    select 32 union
    select 33 union
    select 34 union
    select 35
)
SELECT * FROM datetable

    LEFT JOIN

    (SELECT 
        sls_vendor,
        sls_item,
        sls_units,
        datepart(week,sls_week) AS sls_date
    FROM mytable) AS QRY

    ON temp_week=qry.sls_date

Вывод:

temp_week   sls_vendor  sls_item    sls_units   sls_date
28          NULL        NULL        NULL        NULL
29          NULL        NULL        NULL        NULL
30          NULL        NULL        NULL        NULL
31          NULL        NULL        NULL        NULL
32          NULL        NULL        NULL        NULL
33          1           Test        30          33
34          1           Test        30          34
35          1           Test        30          35

Редактировать: Если вы хотите включить значения всех недель для каждого продавца-продавца, включают перекрестное соединение с четким выбором поставщиков:

;with mytable as (
    select 1 as sls_vendor, 'Test' as sls_item, 30 as sls_units, '8/7/2011' as sls_week union
    select 2 as sls_vendor, 'Test' as sls_item, 30 as sls_units, '8/14/2011' as sls_week union
    select 3 as sls_vendor, 'Test' as sls_item, 30 as sls_units, '8/21/2011' as sls_week
)
,datetable as (
    select 28 as temp_week union
    select 29 union
    select 30 union
    select 31 union
    select 32 union
    select 33 union
    select 34 union
    select 35
)
SELECT * FROM datetable
cross join (select distinct sls_vendor from mytable) v

    LEFT JOIN

    (SELECT 
        sls_vendor,
        sls_item,
        sls_units,
        datepart(week,sls_week) AS sls_date
    FROM mytable) AS QRY

    ON temp_week=qry.sls_date and v.sls_vendor=qry.sls_vendor

Выход:

temp_week   sls_vendor  sls_vendor  sls_item    sls_units   sls_date
28          1           NULL        NULL        NULL        NULL
29          1           NULL        NULL        NULL        NULL
30          1           NULL        NULL        NULL        NULL
31          1           NULL        NULL        NULL        NULL
32          1           NULL        NULL        NULL        NULL
33          1           1           Test        30          33
34          1           NULL        NULL        NULL        NULL
35          1           NULL        NULL        NULL        NULL
28          2           NULL        NULL        NULL        NULL
29          2           NULL        NULL        NULL        NULL
30          2           NULL        NULL        NULL        NULL
31          2           NULL        NULL        NULL        NULL
32          2           NULL        NULL        NULL        NULL
33          2           NULL        NULL        NULL        NULL
34          2           2           Test        30          34
35          2           NULL        NULL        NULL        NULL
28          3           NULL        NULL        NULL        NULL
29          3           NULL        NULL        NULL        NULL
30          3           NULL        NULL        NULL        NULL
31          3           NULL        NULL        NULL        NULL
32          3           NULL        NULL        NULL        NULL
33          3           NULL        NULL        NULL        NULL
34          3           NULL        NULL        NULL        NULL
35          3           3           Test        30          35
0 голосов
/ 27 сентября 2011

Следующий запрос работает в Data.StackExchange. Смотрите здесь . Он получает наибольшее количество сообщений в неделю по баллам.

WITH weeksyears 
     AS (SELECT w.NUMBER AS week, 
                y.NUMBER AS year
         FROM   (SELECT v.NUMBER 
                 FROM   MASTER..spt_values v 
                 WHERE  TYPE = 'P' 
                        AND v.NUMBER BETWEEN 1 AND 52) w, 
                (SELECT v.NUMBER 
                 FROM   MASTER..spt_values v 
                 WHERE  TYPE = 'P' 
                        AND v.NUMBER BETWEEN 2008 AND 2012) y), 
     topPostPerWeek
     AS (SELECT score, 
                Datepart(week, creationdate)       week, 
                Datepart(YEAR, creationdate)       YEAR, 
                Row_number() OVER (PARTITION BY Datepart(wk, creationdate), 
                Datepart( 
                   YEAR, 
                creationdate) ORDER BY score DESC) row 
         FROM   posts) 
SELECT * 
FROM   weeksyears wy 
       LEFT JOIN topPostPerWeekt 
         ON wy.week = t.week 
            AND wy.YEAR = t.YEAR 
WHERE  row = 1 
OR row IS NULL 
ORDER BY wy.YEAR, wy.WEEK
​

Каждая строка до 38 недели в 2008 году пуста, кроме недели и года. А также строки после 35 недели в 2011 году.

Однако, если вы отредактируете запрос и удалите OR row IS NULL, запрос будет действовать так же, как если бы это был INNER JOIN

Я предполагаю, что в вашем ГДЕ есть что-то, что относится к "ПРАВИЛЬНОЙ" таблице. Просто добавьте OR [rightTable.field] IS NULL и все будет хорошо.

0 голосов
/ 27 сентября 2011

У вас работает?

SELECT sls_vendor, 
   sls_item, 
   sls_units, 
   DATEPART(WEEK, sls_week) AS sls_date 
FROM (
    SELECT VALUE = 28 UNION ALL 
    SELECT VALUE = 29 UNION ALL 
    SELECT VALUE = 30 UNION ALL  
    SELECT VALUE = 31 UNION ALL  
    SELECT VALUE = 32 UNION ALL  
    SELECT VALUE = 33 UNION ALL  
    SELECT VALUE = 34 UNION ALL 
    SELECT VALUE = 35
) dates
LEFT JOIN mytable m
ON dates.value = DATEPART(WEEK, m.sls_week)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...