【问题标题】:How to create a matrix from a table with three text columns如何从具有三个文本列的表创建矩阵
【发布时间】:2019-08-22 13:05:17
【问题描述】:

我从一些表中创建了一个视图,其中包含有关某些用户的授权信息的数据。一个例子:

Role         Page         Right

Admin        Home         RW
Manager      Home         RW
Viewer       Home         R
Admin        Overview     RW
Manager      Overview     R
Viewer       Overview     R
Admin        Settings     RW        

我的目标是创建一个像矩阵一样的新视图,显示如下:

Page         Admin     Manager   Viewer

Home          RW         RW        R
Overview      RW         R         R
Settings      RW 

有没有一种方法可以在 SSMS 中完成此任务,请记住将来可能会添加更多角色,而且我不必在每次创建角色时都更新我的代码?

提前致谢!

【问题讨论】:

  • 解决方案是使用动态pivot,但不能在视图中使用动态SQL。我认为您可以使用一些复杂的 XML 函数来做到这一点,也许有人可以解决这个问题。
  • 您肯定无法在视图中执行此操作,因为这需要动态 sql。您的要求中的某些内容必须在此处更改,因为您不能在视图中使用动态 sql。也许您可以使用存储过程?
  • Sean 是对的,Views 只是一个预编译的SELECT 语句;他们不能有DECLAREEXEC之类的东西,甚至不能有多个单个SELECTs。一个函数也不可用,因为你也不能在其中使用EXEC;这使您只剩下一种类型的对象;一个 SP。
  • 那么如果我选择放弃需求的动态部分,有可能吗?
  • 动态元素将在无需干预的情况下扮演您的新角色

标签: sql-server pivot


【解决方案1】:

你应该使用 PIVOT 语句:

SELECT * 
FROM table1 AS t
PIVOT (MAX([RIGHT]) FOR [ROLE] IN ([Admin], [Manager], [Viewer])) AS pvt 

如果您有一个更改角色列,您可以使用如下代码:

DECLARE @ColumnNames NVARCHAR(MAX)  
SELECT @ColumnNames = STUFF(
           (
               SELECT DISTINCT ',['  + [ROLE]+ ']'
               FROM  trtr
               ORDER BY 1 
                      FOR XML PATH('')
           ), 1, 1, '') 

DECLARE @Query AS NVARCHAR(MAX)
SET @Query = 'SELECT * 
FROM trtr AS t
PIVOT (MAX([RIGHT]) FOR [ROLE] IN (' + @ColumnNames + ')) AS pvt'          
EXEC sp_executesql @Query

但是您不能将其用作视图。您将必须创建一个过程

【讨论】:

  • 此解决方案可行,但每次添加新角色时都需要修改脚本,不确定这对于 OP 是否可行
  • 编辑解决方案
【解决方案2】:

已经发布的动态枢轴解决方案是处理这类事情的好方法。我个人觉得 PIVOT 的语法很迟钝,很难保持直截了当。我更喜欢使用条件聚合,因为语法对我来说更简单。性能大致相同,但也需要更少的编码。这是一个完整的工作示例,说明如何使用不同的方法来实现它。

首先是表设置:

if OBJECT_ID('tempdb..#Something') is not null drop table #Something

create table #Something
(
    Role varchar(10)
    , Page varchar(10)
    , [Right] varchar(10)
)

insert #Something values
('Admin', 'Home', 'RW')
, ('Manager', 'Home', 'RW')
, ('Viewer', 'Home', 'R')
, ('Admin', 'Overview', 'RW')
, ('Manager', 'Overview', 'R')
, ('Viewer', 'Overview', 'R')
, ('Admin', 'Settings', 'RW')

这里需要的实际代码非常少,因为我们正在使用数据为我们构建动态 sql。

declare @SQL nvarchar(max) = ''

select @SQL = @SQL + ', Max(Case when Role = ''' + Role + ''' then [Right] end) as ' + QuoteName(Role)
from #Something
group by Role

set @SQL = N'select Page ' + @SQL + ' from #Something group by Page order by Page'

exec sp_executesql @SQL

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-14
    • 1970-01-01
    • 2020-02-05
    • 1970-01-01
    • 2013-03-29
    相关资源
    最近更新 更多