Как преобразовать строки в новые столбцы в таблице отношений m к n? - PullRequest
1 голос
/ 01 октября 2019

Мне нужна помощь с проблемой.

Я работаю над базой данных Microsoft с SQL, и у меня есть таблица, похожая на эту:

|*Name*|*Permissions*|
|App1  |Permission 1 |
|App1  |Permission 2 |
|App1  |Permission 3 |
|App2  |Permission 1 |
|App2  |Permission 2 |
|App2  |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 |

Возможно, что приложения имеют другое количество разрешений,но если это так, было бы хорошо, если бы эти пустые столбцы были заполнены значениями NULL.

Надеюсь, вы мне поможете. Если вам нужна дополнительная информация, просто напишите мне. Поскольку я новичок в StackOverflow, я не профессионал в написании вопроса.

Спасибо!

Ответы [ 4 ]

1 голос
/ 01 октября 2019

Для этого вы можете использовать оператор PIVOT . Пример приведен ниже.

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 количество разрешений, вам, возможно, придется использовать динамическое вращение .

0 голосов
/ 01 октября 2019

Вы также можете попробовать это ИСПОЛЬЗОВАТЬ CTE

;with cte as (
SELECT *
        ,ROW_NUMBER() over(partition by Name order by Permissions ) rn
FROM YourTable
) 

select      Name
            ,MAX(case   when rn=1 then Permissions   end) Permission1
            ,MAX(case   WHEN rn=2 then Permissions  end) Permission2
            ,MAX(case   WHEN rn=3 then Permissions  end) Permission3
FROM cte 
group by Name
0 голосов
/ 01 октября 2019

Вы можете использовать PIVOT для этого типа запроса:

A mockup-сценарий для имитации вашей проблемы

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 мы можем создать значение, которое позже сможем использовать в качестве имени столбца сводной диаграммы.

0 голосов
/ 01 октября 2019

Если у вас есть максимальное количество разрешений, которые вас волнуют (скажем, три), вы можете просто использовать условное агрегирование (или pivot):

select a.name,
       max(case when seqnum = 1 then a.permission end) as permission_1,
       max(case when seqnum = 2 then a.permission end) as permission_2,
       max(case when seqnum = 3 then a.permission end) as permission_3
from (select a.*,
             row_number() over (partition by a.name order by a.name) as seqnum
      from apps a
     ) a
group by a.name;

Если вы не знаете, сколькостолбцы, которые вы хотите вернуть, затем вам нужно использовать динамический SQL, и запрос немного сложнее.

...