2013-09-25 4 views
1

У меня есть 3 таблицы в базе данных SQL Server 2008. Первая таблица содержит имена пользователей, второй содержит привилегии и последние ссылки первые две таблицы:Таблица возврата из SQL Query

ПОЛЬЗОВАТЕЛИ (ID целое, NAME VARCHAR (20));

PRIVS (ID целое число, NAME VARCHAR (50));

USERS_PRIVS (USERID integer, PRIVID integer);

Например, таблица USERS имеет следующее:

1, Adam 
2, Benjamin 
3, Chris 

Таблица PRIVS имеет:

1, Add Invoice 
2, Edit Invoice 
3, Delete Invoice 

Таблица USERS_PRIVS имеет:

1, 1 
1, 2 
1, 3 
2, 1 
2, 2 
3, 1 

Ищу для способ создания SQL-запроса, который бы возвращал примерно следующее:

  Add Invoice Edit Invoice Delete Invoice 
Adam  Y    Y    Y 
Benjamin Y    Y    N 
Chris  Y    N    N 

Возможно ли это, используя функцию поворота?

+2

Да. Существует много примеров «PIVOT» на этом сайте и в Интернете; что вы пробовали? –

+0

@JonofAllTrades: Я попробовал несколько различных сводных предложений. Проблема, с которой я столкнулась, заключается в том, чтобы заголовки столбцов из таблицы PRIVS вместо hardcoding их в SQL, как и все приведенные ниже рекомендации. – Caynadian

ответ

1
SELECT Name, [Add Invoice],[Edit Invoice],[Delete Invoice] FROM 
(SELECT U.Name AS Name, P.Name AS PrivName FROM USERS_PRIVS UP 
    INNER JOIN Users U ON UP.UserID = U.id 
    INNER JOIN Privs P ON UP.PrivID = P.id) SB 
PIVOT(
count(SB.PrivName) 
FOR SB.PrivName in ([Add Invoice],[edit Invoice],[Delete Invoice])) AS Results 

EDIT 1: Вы должны будете использовать некоторые динамические SQL тогда.

DECLARE @query AS NVARCHAR(MAX); 
DECLARE @privColumnNames AS NVARCHAR(MAX); 

select @privColumnNames = STUFF((SELECT distinct ',' + QUOTENAME(Name) 
            FROM PRIVS FOR XML PATH(''), TYPE 
           ).value('.', 'NVARCHAR(MAX)'), 1, 1, ''); 

SELECT @query = 
'SELECT * 
FROM 
(SELECT U.Name AS Name, P.Name AS PrivName FROM USERS_PRIVS UP 
    INNER JOIN Users U ON UP.UserID = U.id 
    INNER JOIN Privs P ON UP.PrivID = P.id) SB 
PIVOT(
count(SB.PrivName) 
FOR SB.PrivName in (' + @privColumnNames + ')) AS Results '; 

execute(@query); 

Я позаимствовал XML материал здесь Dynamic Pivot Columns in SQL Server

+0

Это работает, но я надеялся избежать жесткого кодирования каждого имени привилегии в качестве заголовка столбца. Есть ли способ динамически установить имена столбцов на основе привилегий в таблице? – Caynadian

+0

@ Caynadian см. Редактировать 1. Он использует динамический sql для получения списка столбцов из вашей таблицы Privs – Josh

+0

Это работает потрясающе! Благодаря! – Caynadian

1

Демо-версия на SqlFiddle.

with cl 
as (
select u.NAME , case when p.ID = 1 then 'Y' else 'N' end 'Add Invoice', 
case when p.ID = 2 then 'Y' else 'N' end 'Edit Invoice', 
case when p.ID = 3 then 'Y' else 'N' end 'Delete Invoice' 
from USERS u inner join USERS_PRIVS up on u.ID = up.USERID 
inner join PRIVS p on up.PRIVID = p.ID 
) 

select NAME, MAX([Add Invoice]) 'Add Invoice', 
MAX([Edit Invoice]) 'Edit Invoice', 
MAX([Delete Invoice]) 'elete Invoice' 
from cl 
group by NAME 

Вот демо на SqlFiddle.

select NAME , case when [Add Invoice] = 1 then 'Y' else 'N' end 'Add Invoice', 
case when [Edit Invoice] = 1 then 'Y' else 'N' end 'Edit Invoice', 
case when [Delete Invoice] = 1 then 'Y' else 'N' end 'Delete Invoice' 
from (
select u.NAME, p.NAME as pname 
from USERS u inner join USERS_PRIVS up on u.ID = up.USERID 
inner join PRIVS p on up.PRIVID = p.ID 
) p 
pivot(count(pname) for pname in ([Add Invoice], [Edit Invoice], [Delete Invoice])) as pvt 
+0

Ваш второй скрипт работает, но я надеялся избежать жесткого кодирования каждого имени привилегии в качестве заголовка столбца. Есть ли способ динамически установить имена столбцов на основе привилегий в таблице? – Caynadian

1

Попробуйте это:

select 
    name, 
    CASE [1] WHEN 1 THEN 'Y' ELSE 'N' END as 'Add Invoice', 
    CASE [2] WHEN 1 THEN 'Y' ELSE 'N' END as 'Edit Invoice', 
    CASE [3] WHEN 1 THEN 'Y' ELSE 'N' END as 'Delete Invoice' 
from 
    (select name, userId, privid, 1 temp from users_privs join users on id = userid) as sourceTable 
    pivot(min(temp) for privid in ([1], [2], [3])) as pivotTable 
+0

Это работает, но я надеялся избежать жесткого кодирования каждого имени привилегии в качестве заголовка столбца. Есть ли способ динамически установить имена столбцов на основе привилегий в таблице? – Caynadian

Смежные вопросы