Sql 如何将m到n关系表中的行转换为新列?

Sql 如何将m到n关系表中的行转换为新列?,sql,tsql,many-to-many,multiple-columns,Sql,Tsql,Many To Many,Multiple Columns,我需要一些帮助来解决一个问题 我正在使用SQL处理一个microsoft数据库,我有一个与此表类似的表: |*Name*|*Permissions*| |App1 |Permission 1 | |App1 |Permission 2 | |App1 |Permission 3 | |App2 |Permission 1 | |App2 |Permission 2 | |App2 |Permission 3 | 因此,这是一种m到n的关系,因为有多个权限分配给一个应用程序,但也有多

我需要一些帮助来解决一个问题

我正在使用SQL处理一个microsoft数据库,我有一个与此表类似的表:

|*Name*|*Permissions*|
|App1  |Permission 1 |
|App1  |Permission 2 |
|App1  |Permission 3 |
|App2  |Permission 1 |
|App2  |Permission 2 |
|App2  |Permission 3 |
因此,这是一种m到n的关系,因为有多个权限分配给一个应用程序,但也有多个应用程序使用相同的权限

我已经尝试过使用distinct将表与自身连接起来,如下所示:

select distinct apps1.name, apps2.permissions from Apps apps1
join Apps apps2
where apps2.name IN
(SELECT distinct name from Apps);
|*Name*|*Permission1*|*Permission2*|*Permission3*|
|App1  |Permission 1 |Permission 2 |Permission 3 |
|App2  |Permission 1 |Permission 2 |Permission 3 |
但这并没有让我得到我想要的结果

我希望得到如下结果:

select distinct apps1.name, apps2.permissions from Apps apps1
join Apps apps2
where apps2.name IN
(SELECT distinct name from Apps);
|*Name*|*Permission1*|*Permission2*|*Permission3*|
|App1  |Permission 1 |Permission 2 |Permission 3 |
|App2  |Permission 1 |Permission 2 |Permission 3 |
应用程序有可能获得不同数量的权限,但如果是这样的话,如果这些空列中填充了空值就可以了

我希望你能帮助我。
如果需要进一步的信息,请写信给我。因为我是StackOverflow的新手,所以我不是写这个问题的专业人士。

如果您关心的权限最大,比如三个,那么您可以使用条件聚合或透视:

如果不知道要返回多少列,则需要使用动态SQL,查询会稍微复杂一些。

您可以使用PIVOT进行此类查询:

模拟问题的实体模型场景

DECLARE @mockupTable TABLE([Name] VARCHAR(100),[Permissions] VARCHAR(100));
INSERT INTO @mockupTable VALUES
 ('App1','Permission 1')
,('App1','Permission 2')
,('App1','Permission 3')
,('App2','Permission 1')
,('App2','Permission 2')
,('App2','Permission 3');
-询问

SELECT p.*
FROM
(
    SELECT t.*
          ,CONCAT('Permission',ROW_NUMBER() OVER(PARTITION BY t.[Name] ORDER BY t.[Permissions])) AS ColumnName
    FROM @mockupTable t
) tbl
PIVOT
(
    MAX(tbl.[Permissions]) 
    FOR tbl.ColumnName 
    IN(Permission1,Permission2,Permission3,Permission4 /*add as many as you need*/)
) p;
简而言之:

通过CONCAT和ROW_NUMBER,我们可以创建一个值,稍后我们可以将其用作轴的列名。

您可以使用该运算符。下面给出了一个例子

CREATE TABLE #Permission
(
 Name       VARCHAR(10)
,Permission VARCHAR(25)
)

INSERT INTO #Permission (Name, Permission) VALUES
('App1', 'Permission 1')
,('App1', 'Permission 2')
,('App1', 'Permission 3')
,('App2', 'Permission 1')
,('App2', 'Permission 2')
,('App2', 'Permission 3')
,('App3', 'Permission 2');


SELECT * 
FROM
    (
    SELECT Name, Permission FROM #Permission
    ) AS A
PIVOT
    (
    MAX(Permission)
    FOR Permission IN ([Permission 1], [Permission 2], [Permission 3])
    ) AS PivotTable

DROP TABLE #Permission;
如果您有n个权限,则可能必须使用。

您也可以使用CTE尝试此操作
非常感谢您的快速回复,我需要根据我的实际代码调整它,以检查它是否有效,但我无法理解您使用seqnum的目的,请您解释一下好吗?谢谢@s、 宾克。这是为权限分配一个数字所必需的,这样您就可以将它们放在单独的列中。哦,我明白了,谢谢!不幸的是,ORDERBY select null在我的数据库中不起作用,但我看不出不应该按名称排序的原因。通过此更正,您的代码工作正常,谢谢@s、 宾克。这很奇怪。SQL Server支持order by select null,但名称也可以。我很确定,我们看到的权限值只是变量值的占位符。。。这就是为什么我的PIVOT方法从每个应用程序的计数器创建PIVOT的列名。。。