Сводная таблица SQL, возвращающая NULL для несуществующих значений дочерней таблицы - PullRequest
0 голосов
/ 12 марта 2011

У меня есть типичная установка RDMS, где записи в основной таблице могут иметь дополнительные записи в связанной таблице через соединение M2M. Я пытаюсь PIVOT эти данные, но в случаях, когда нет отношения, я хочу вернуть значение по умолчанию. Соединение, которое у меня есть ниже, возвращает NULL.

select * 
from
(
    SELECT s.Biz_Name, la.Name AS Association, ISNULL(i.Location, 'Default') as Location
    FROM  dbo.ShopAssociations sa 
    INNER JOIN dbo.LookupAssociations la 
        ON sa.AssociationID = la.AssociationID 
    RIGHT JOIN dbo.Basic_Shop_Info s 
        ON sa.ShopID = s.ShopID 
    INNER JOIN dbo.Images i 
        ON la.ImageID = i.ImageID
) DataTable
PIVOT 
(
    min(Location) 
    for association in
        ([OnCall],[OCGuy],[ASCLogo],[ASC_OtherSt],[ASE],[AASP],[AASP_PA],
        [ASE_BlueSeal],[AAA],[AAA-B],[ASA],[ATRA],[ICAR],[CAA],[ACDelco],
        [Cert],[ASC],[BBB],[Goodyear],[Limos],[RVs],[Bosch],[NARSA],
        [DiscTire],[BigO],[Tires],[Firestone],[ASCCA],[JustTires],[ASE_Blue])
) PivotTable

Вывод выглядит так:

BizName          OnCall     OCGuy     ASCLogo ASC_OtherSt ASE ...
"Wonderful Biz"  somevalue  somevalue NULL    somevalue   NULL

Я пытаюсь добиться того, чтобы дочерняя запись не существовала в INNER JOIN от Basic_Shop_Info до ShopAssociations, и мы получаем «По умолчанию» вместо NULL. Я пробовал ISNULL (), Coalesce () и даже оператор CASE, все с одинаковыми результатами.

1 Ответ

0 голосов
/ 18 августа 2012

Судя по вашему комментарию, вы нашли решение. Я только отвечаю на это, чтобы дать предложение, основанное на факте, что вы поворачиваете так много столбцов, и все они жестко закодированы. Вы можете использовать динамический SQL для PIVOT, и ваш запрос будет выглядеть примерно так:

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Name) 
                    from dbo.LookupAssociations
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsPivot = STUFF((SELECT distinct ', IsNull(' + QUOTENAME(Name) +', ''Default'')'
                    from dbo.LookupAssociations
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT Bizname, ' + @colsPivot + ' from 
            (
                SELECT s.Biz_Name, la.Name AS Association, ISNULL(i.Location, ''Default'') as Location
                FROM  dbo.ShopAssociations sa 
                INNER JOIN dbo.LookupAssociations la 
                    ON sa.AssociationID = la.AssociationID 
                RIGHT JOIN dbo.Basic_Shop_Info s 
                    ON sa.ShopID = s.ShopID 
                INNER JOIN dbo.Images i 
                    ON la.ImageID = i.ImageID
            ) x
            pivot 
            (
                min(Location)
                for association in (' + @cols + ')
            ) p 
            '

execute(@query)

Значение @colsPivot добавляет IsNull() вокруг каждого из вас столбцов, чтобы вы могли поставить на место значение Default. Но это должно дать тот же результат, что и исходный запрос, где все было жестко закодировано.

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

...