Замените NULL на 0 в сводной таблице в сочетании с avg CAST - PullRequest
3 голосов
/ 05 июня 2019

Я пытаюсь заменить NULL на 0 в выводе моего столбца TagValue в сочетании с avg Cast. Я попробовал следующий запрос:

ISNULL(TRY_CAST(TagValue AS DECIMAL(18,2)),0) AS TagValue 

в коде


DECLARE @cols AS NVARCHAR(MAX),
        @query AS NVARCHAR(MAX)

SELECT @cols = STUFF((SELECT  ',' + QUOTENAME(TagID)
                      FROM [table]
                      GROUP BY TagID
                      ORDER BY TagID
                FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')

SET @query = 'SELECT   TimeStamp,  ' + @cols + ' from 
             (
                select  DATEADD(minute,DATEDIFF(minute,0,TimeStamp)/5*5,0) AS  TimeStamp, TagID ,   ISNULL(TRY_CAST(TagValue AS DECIMAL(18,2)),0) AS TagValue 
                from [table]
                 -- Where TagValue isnull(TagValue,1)=0
                Group By datediff(minute, 0,Timestamp)/5,TagID, TagValue
            ) x
            pivot 
            (
                AVG(TagValue)
                for TagID in ( ' + @cols + ' )
            ) p '

EXEC(@query)


хотя ошибок нет, выходные данные запроса показывают NULL.

Я также пробовал следующие запросы:


SELECT @cols = STUFF((SELECT  ','', IsNull(' + QUOTENAME(TagID)+', 0) as '+QUOTENAME(TagID)
                      FROM [table]
                      GROUP BY TagID
                      ORDER BY TagID
                FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')
...
SET @query = 'SELECT TimeStamp,  ' +ISNULL(@cols,0) + ' from ...

Также функция Case:

CASE When (TagValue= NULL) THEN 0 ELSE TRY_CAST(TagValue AS DECIMAL(18,2)) END AS TagValue

Буду очень признателен за вашу помощь! Большое спасибо

1 Ответ

1 голос
/ 05 июня 2019

Оператор PIVOT работает с набором постоянных значений. Эти значения должны быть явно записаны и не могут ссылаться на другие столбцы, содержать выражения или функции, такие как ISNULL.

DECLARE @Mascot TABLE (
    Amount INT,
    Mascot VARCHAR(100))

INSERT INTO @Mascot (
    Amount,
    Mascot)
VALUES
    (10, 'Dog'), (5, 'Dog'),
    (6, 'Cat'),
    (12, 'Weird Spider'), (8, 'Weird Spider'), (5, 'Weird Spider')

SELECT
    P.*
FROM
    @Mascot AS M
    PIVOT (
        SUM(M.Amount)
        FOR Mascot IN ([Dog], [Cat], [Weird Spider], [Cameleon])
    ) AS P

Результат:

Dog     Cat     Weird Spider    Cameleon
15      6       25              NULL

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

SELECT
    P.Dog, -- We can reference the pivoted columns by name
    P.Cat,
    P.[Weird Spider],
    P.Cameleon
FROM
    @Mascot AS M
    PIVOT (
        SUM(M.Amount)
        FOR Mascot IN ([Dog], [Cat], [Weird Spider], [Cameleon])
    ) AS P

Мы можем сделать любую модификацию, какую захотим, в качестве выражения в списке столбцов SELECT:

SELECT
    P.Dog,
    P.Cat,
    P.[Weird Spider],
    ISNULL(P.Cameleon, 0) AS Cameleon,
    Total = 
        ISNULL(P.Dog, 0) +
        ISNULL(P.Cat, 0) +
        ISNULL(P.[Weird Spider], 0) +
        ISNULL(P.Cameleon, 0)
FROM
    @Mascot AS M
    PIVOT (
        SUM(M.Amount)
        FOR Mascot IN ([Dog], [Cat], [Weird Spider], [Cameleon])
    ) AS P

Результат:

Dog     Cat     Weird Spider    Cameleon    Total
15      6       25              0           46

Таким образом, когда вы строите свой динамический свод, значения сводки должны быть точным содержанием значения, хранящегося в наборе, который вы собираетесь сводить ('Dog', 'Cat' и т. Д.), В то время как на SELECT список вы можете построить любое выражение, которое вы хотите (ISNULL([Dog], 0) AS [Dog]).


Таким образом, решение для вашего случая состоит в том, чтобы использовать 2 разных @cols, один с нулевыми проверками в списке SELECT, а другой для поворота значений.

DECLARE @cols_select AS NVARCHAR(MAX),
        @cols_pivot AS NVARCHAR(MAX),
        @query AS NVARCHAR(MAX)

SELECT @cols_pivot = STUFF((SELECT  ',' + QUOTENAME(TagID)
                      FROM [table]
                      GROUP BY TagID
                      ORDER BY TagID
                FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')

SELECT @cols_select = STUFF((SELECT  ','', IsNull(' + QUOTENAME(TagID)+', 0) as '+QUOTENAME(TagID)
                      FROM [table]
                      GROUP BY TagID
                      ORDER BY TagID
                FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')

SET @query = 'SELECT   TimeStamp,  ' + @cols_select + ' from 
             (
                select  DATEADD(minute,DATEDIFF(minute,0,TimeStamp)/5*5,0) AS  TimeStamp, TagID ,   ISNULL(TRY_CAST(TagValue AS DECIMAL(18,2)),0) AS TagValue 
                from [table]
                 -- Where TagValue isnull(TagValue,1)=0
                Group By datediff(minute, 0,Timestamp)/5,TagID, TagValue
            ) x
            pivot 
            (
                AVG(TagValue)
                for TagID in ( ' + @cols_pivot + ' )
            ) p '

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