具有子类别的动态数据透视表

时间:2016-10-04 12:29:03

标签: sql-server

我目前有一个电子邮件类别列表,我列出了他们选择的人和类别。

我现在有一个要求,即每个电子邮件类别可能会分配一个ID,链接到该类别中的类型。

例如,名为Parent的电子邮件类别可以包含链接到类表的特定类ID的列。 所以我现在需要列出所选的类别以及"子类别"。

我的表类似如下

Name   CategoryName ClassId
Test1  Parent       23         //23 is reception class
Test1  General      Null
Test2  Parent       Null
Test3  Committee    Null
Test3  Parent       24        // 24 is year 1

我想要的是

Name  | Parent  | Parent-Reception | Parent-Year1 | Committee | General      
Test1 | 1       | 1                | 0            | 0         | 1
Test2 | 1       | 0                | 0            | 0         | 0
Test3 | 1       | 0                | 1            | 1         | 0

我正在使用以下sql来获取没有链接类的类别。

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

SET @colsSelect = STUFF((SELECT distinct ', ISNULL(' + QUOTENAME(c.CategoryName) + ',0) AS ' + QUOTENAME(c.CategoryName)
            FROM   dbo.EmailCategory c           
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

        SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.CategoryName) 
            FROM   dbo.EmailCategory c                
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

        set @query = 'SELECT FirstName, LastName, Email, ' + @colsSelect + ' from 
            (
                SELECT DISTINCT                             
                            dbo.[User].Name,                                
                            dbo.EmailCategory.CategoryName,
                            1 as assigned
                FROM         dbo.[User]  INNER JOIN
                      dbo.EmailPreferences ON dbo.[User].ID = dbo.EmailPreferences.UserID LEFT OUTER JOIN
                      dbo.EmailCategory ON dbo.EmailPreferences.EmailCategoryID = dbo.EmailCategory.ID
                WHERE     
                    (dbo.[User].Email <> '''') AND (dbo.[User].Email IS NOT NULL)              ) x
            pivot 
            (
                 max(assigned)
                for CategoryName in (' + @cols + ')
            ) p '

            execute(@query)

使用这种类型的sql甚至可以吗?

1 个答案:

答案 0 :(得分:1)

一个相当容易(我猜)的解决方案是创建一个视图并使用它而不是当前的表。

在此视图中,您可以展平类别和子类别,以便您可以使用当前代码几乎不做任何更改:

select 
  Name, 
  CategoryName
from emails
union
select 
  Name, 
  CategoryName +  '-' + c.SubName
from emails e
join classes c on c.id = e.ClassId

应返回类似(来自您给定的样本)的内容

Name    CategoryName
Test1   General
Test1   Parent
Test1   Parent-Reception
Test2   Parent
Test3   Committee
Test3   Parent
Test3   Parent-Year1

现在,您将代码中对EmailCategory的引用替换为该新视图,您就应该完成。