SQL数据透视表为不存在的子表值返回NULL

SQL数据透视表为不存在的子表值返回NULL,sql,null,pivot,default-value,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.Lookup

我有一个典型的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
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)

我试图实现的是,如果从基本商店信息到商店关联的内部连接中不存在子记录,我们将得到“Default”而不是NULL。我尝试了ISNULL()、Coalesce()甚至一个CASE语句,都得到了相同的结果。

根据您的评论,您似乎找到了解决方案。我回答这个问题只是为了提供一个建议,基于这样一个事实,您正在旋转这么多列,它们都是硬编码的。您可以将动态SQL用于数据透视,您的查询如下所示:

BizName          OnCall     OCGuy     ASCLogo ASC_OtherSt ASE ...
"Wonderful Biz"  somevalue  somevalue NULL    somevalue   NULL
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()
,以便您可以放置
默认值。但这应该提供与原始查询相同的结果,其中所有内容都是硬编码的

这将在运行时获得列列表,这样您就不必硬编码任何内容,它将接受新值,而无需更改查询

我得到了这个:

    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);

这里有一个技巧,我在顶部选择中添加了每个数据透视列,例如选择ISNULL([OnCall],“default”)作为[OnCall]。。。任何有更好想法的人请告诉我,谢谢!这不是黑客,这是正确的答案!