2014-03-05 40 views
0

我有一个权限系统,用于定义用户对特定项目的访问权限。SQL Query&unpivot语法

我需要一个报告页面来显示成员及其对项目的访问权限。

的表需要是这样的:

+---------+--------+--------+------+--------+ 
| Members | Item 1 | Item 2 | .... | Item N | 
+---------+--------+--------+------+--------+ 
| Member1 | x | + | .... | + | 
+---------+--------+--------+------+--------+ 
| Member2 | + | x | .... | + | 
+---------+--------+--------+------+--------+ 

我有一个3表连接查询上市的成员,他们可以访问的项目,但我不能把它转换成旋转的语法。

Select members.id memberID, members.name memberName, items.name as item 
From members 
Left Join member_permission On memberID = members.id 
Left Join items On items.id = member_permission.itemID 

这是不工作的查询,我有:

Select memberName, itemName 
From (
    select members.id, members.name, item.name as itemName 
    from members 
    Left Join member_permission On memberID = members.id 
    Left Join item On item.id = member_permission.itemID 
) p 
Unpivot 
(itemName For name IN (item.name)) as unp 

和错误我收到:在UNPIVOT操作冲突

列名“名”指定与现有UNPIVOT参数中的列名称。

我创建了一个例子与Sqlfiddle

回答

3

打你不需要使用UNPIVOT此查询。 UNPIVOT用于将多列转换为多行。您只需要应用PIVOT功能将您的项目变成列。

我首先建议使用像row_number()窗口函数来创建新的列标题,然后应用旋转功能:

select id, name, Item1, Item2, Item3 
from 
(
    select members.id, members.name, items.name as item, 
    'item'+ 
     cast(row_number() over(partition by members.id 
          order by members.id) as varchar(10)) col 
    from members 
    Left Join member_permission 
    On memberID = members.id 
    Left Join items 
    On items.id = member_permission.itemID 
) d 
pivot 
(
    max(item) 
    for col in (Item1, Item2, Item3) 
) piv; 

SQL Fiddle with Demo。然后,如果你有一个未知的数值的查询可能需要使用动态SQL:

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

select @cols = STUFF((SELECT ',' + QUOTENAME('item'+cast(seq as varchar(10))) 
        from 
        (
         select row_number() over(partition by memberid 
               order by memberid) seq 
         from member_permission 
        ) d 
        group by seq 
        order by seq 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = N'SELECT id, name, ' + @cols + N' 
      from 
      (
       select members.id, members.name, items.name as item, 
       ''item''+ 
        cast(row_number() over(partition by members.id 
             order by members.id) as varchar(10)) col 
       from members 
       Left Join member_permission 
       On memberID = members.id 
       Left Join items 
       On items.id = member_permission.itemID 
      ) x 
      pivot 
      (
       max(item) 
       for col in (' + @cols + N') 
      ) p ' 

execute sp_executesql @query; 

SQL Fiddle with Demo

+0

感谢您的回答,一个一个细节;我怎样才能使用项目名称作为列名?即:“蓝色项目,红色项目”而不是“项目1,项目2” – dvdmn

+0

@dvdnhm您仍然可以使用相同的过程,但不是使用'rownumber()'生成列的列表,您可以使用你的专栏。 – Taryn