Как правильно кодировать свод с динамическим оператором SQL? - PullRequest
0 голосов
/ 17 апреля 2019

Я пытаюсь настроить сводную диаграмму, чтобы показать ежедневные общие продажи за последние 7 дней, но я получаю сообщение об ошибке при попытке запустить скрипт.

Это SQL-скрипт:

DECLARE @dates AS TABLE (PurchaseDate DATETIME)

DECLARE @basedate DATETIME,
        @offset INT,
        @maxdays INT

SELECT @basedate = GETDATE(), @offset = 1, @maxdays = 7

WHILE (@offset <= @maxdays)
BEGIN
    INSERT INTO @dates 
    VALUES (GETDATE() - @offset)

    SELECT @offset = @offset + 1
END

DECLARE @query  NVARCHAR(MAX)
SET @query = '
SELECT * FROM (
    SELECT  Items.ParentSku, CAST(Orders.PurchaseDate AS date) as [Date], SUM(OrderItems.QuantityOrdered) AS Units
    FROM OrderItems JOIN Items ON OrderItems.ASIN = Items.ASIN JOIN Orders ON OrderItems.AmazonOrderID = Orders.AmazonOrderID
    WHERE Orders.PurchaseDate >= Convert(DateTime, DATEDIFF(DAY, 30, GETDATE()))
    GROUP BY Items.ParentSku, CAST(Orders.PurchaseDate AS date)
) Summary
PIVOT 
(
    SUM(Summary.Units)
    FOR Summary.Date IN (' + @dates + ')
) AS DatePivot'

EXEC (@query)

Я получаю эту ошибку:

Сообщение 137, Уровень 16, Состояние 1, Строка 24
Должен объявить скалярную переменную "@dates".

Я не смог понять, почему это не работает. Может кто-нибудь помочь?

Ответы [ 2 ]

0 голосов
/ 17 апреля 2019

Спасибо всем за помощь. Я смог построить строку с датами, и теперь запрос работает. Пожалуйста, смотрите ниже обновленный запрос и вывод:

DECLARE @basedate DATETIME = GETDATE(),
        @offset INT = 1,
        @maxdays INT = 7,
        @dates NVARCHAR(MAX) = '',
        @query NVARCHAR(MAX) = ''

WHILE (@offset < @maxdays)
BEGIN
    SET @dates = @dates + '[' + CONVERT(NVARCHAR(MAX),DATEADD(DD,-@offset,GETDATE()),101) + '], '
    SET @offset = @offset + 1
END
SET @dates = @dates + '[' + CONVERT(NVARCHAR(MAX),DATEADD(DD,-@offset,GETDATE()),101) + ']'

SET @query = '
SELECT * FROM (
    SELECT  Items.ParentSku, CAST(Orders.PurchaseDate AS DATE) as [Date], SUM(OrderItems.QuantityOrdered) AS Units
    FROM OrderItems JOIN Items ON OrderItems.ASIN = Items.ASIN JOIN Orders ON OrderItems.AmazonOrderID = Orders.AmazonOrderID
    WHERE Orders.PurchaseDate >= DATEADD(DD,-' + CONVERT(NVARCHAR(MAX),@maxdays+1) +',GETDATE())
    GROUP BY Items.ParentSku, CAST(Orders.PurchaseDate AS date)
) Summary
PIVOT (
    SUM(Summary.Units)
    FOR Summary.Date IN (' + @dates + ')) AS DatePivot'

EXEC (@query)

Выход:

ParentSku 16.04.2009 г. 15.04.2009 г. 14.04.2009 г. 13.04.2009 г. 04.12.2009 г. 04.04.2017 г. AMZN17FA026 5 10 8 7 8 5 6 AMZN17FA027 3 1 1 4 3 4 1 AMZN17FA028 NULL 1 1 NULL 1 2 NULL AMZN17FA029 NULL NULL NULL NULL NULL NULL AMZN17FA030 2 1 NULL 1 NULL NULL NULL AMZN17FA031 NULL NULL 2 NULL NULL NULL NULL AMZN17FA036 NULL NULL 3 NULL NULL NULL NULL

Мой следующий вопрос: как изменить NULL на 0. Функция ISNULL у меня не сработала, когда я пытаюсь использовать ее при агрегации. Спасибо!

0 голосов
/ 17 апреля 2019

Вам нужно использовать обычную строку в этом контексте, а не переменную таблицы. Вы можете создать строку из таблицы памяти следующим образом:

DECLARE @dates AS TABLE (PurchaseDate DATETIME)

INSERT @dates (PurchaseDate) VALUES ('1/1/2019'), ('1/2/2019'), ('1/3/2019')

DECLARE @dates_as_string VARCHAR(max) = ''

SELECT @dates_as_string += CASE WHEN @dates_as_string = '' THEN '' ELSE ', ' END + '''' + CONVERT(VARCHAR(10), PurchaseDate, 121) + ''''
FROM @dates

PRINT @dates_as_string

, а затем используйте @dates_as_string в FOR Summary.Date IN (' + @dates + ') (так будет FOR Summary.Date IN (' + @dates_as_string + '));

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...