SQL Pivot表为不存在的子表值返回NULL

时间:2011-03-12 00:59:52

标签: sql null pivot default-value

我有一个典型的RDMS设置,主表中的记录可以通过M2M连接在相关表中具有可选记录。我试图捕获这些数据,但在没有关系的情况下,我想返回一个默认值。我在下面的连接返回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

我想要实现的是,如果从Basic_Shop_Info到ShopAssociations的INNER JOIN中不存在子记录,我们得到“Default”而不是NULL。我已经尝试过ISNULL(),Coalesce()甚至一个CASE语句,都具有相同的结果。

2 个答案:

答案 0 :(得分:0)

根据您的评论,听起来您找到了解决方案。我只是回答这个问题,根据你转动这么多列的事实提供一个建议,它们都是硬编码的。您可以将动态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值。但是这应该提供与原始查询相同的结果,其中所有内容都是硬编码的。

这将在运行时获取列的列表,因此您不必对任何内容进行硬编码,它将接受新值而无需更改查询。

答案 1 :(得分:0)

我知道了:

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

    select @cols = STUFF((SELECT ',' + QUOTENAME(c.col+cast(rn as varchar(10))) 
                    from 
                    (
                      select row_number() over(partition by person_nbr 
                                               order by person_nbr,first_name,        last_name, medication_name) rn
                      from TA_PIVOT
                    ) d
                    cross apply
                    (
                      select 'diag' col, 1 sort
                    ) c
                    group by col, rn, sort
                    order by rn, sort
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

    set @query = 'SELECT person_nbr, first_name, last_name,medication_name,' + @cols + '
              from
              (
                select person_nbr,first_name,last_name,medication_name,
                  col+cast(rn as varchar(10)) col,
                  value
                from
                (
                 -- when you perform an unpivot the datatypes have to be the same. 
                 -- you might have to cast the datatypes in this query
                  select person_nbr,first_name,last_name, medication_name,   cast(icd_code_id as varchar(500)) diag,
                    row_number() over(partition by person_nbr order by person_nbr,   first_name, last_name,medication_name) rn
                  from ta_pivot
                ) src
                unpivot
                (
                  value
                  for col in (diag)
                ) unpiv
              ) d
              pivot 
              (
                  max(value)
                  for col in (' + @cols + ')
              ) p '

    execute(@query);
相关问题