Как мне создать сводный запрос для этого простого случая? - PullRequest
1 голос
/ 01 июня 2010

У меня очень простой запрос, который мне нужно развернуть, но я не знаю, как превратить его в сводную таблицу из того, что я прочитал в литературе. Все, что я прочитал, содержит жестко закодированные столбцы или слишком сложно. Это должно быть проще, или я просто не могу понять CTE.

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

user  client
1 a
1 b
1 c
2 a
2 d
3 a
3 d
3 e
3 f

Общее количество клиентов может быть около 20 или около того. Некоторые пользователи могут получить доступ ко всем клиентам, другие только один или два. То, что я хочу видеть, это:

user a b c d e f
1 x x x
2 x   x
3 x   x x x

Сюда входят три таблицы: таблица пользователей, таблица клиентов и таблица перекрестных ссылок (разрешения), которая объединяет пользователей с их клиентами.

Я пробовал что-то вроде следующего, но это, очевидно, не работает (или даже компилируется).

with usersclients(user_name, clients, client_code)
as
(
 select users.user_name
 from clients cli
  left join
  (select u.user_id, user_name, c.client_id, client_code, client_name 
   from permissions p inner join clients c on p.client_id = c.client_id
   inner join users u on u.user_id = p.user_id
  ) user
  on user.client_id = cli.client_id
)
select *
from usersclients
pivot (max(client_code) for client_code in (select client_code from clients)) as P

Любые подсказки, которые больше всего ценятся!

1 Ответ

2 голосов
/ 01 июня 2010

Я полагаю, что SQL-сервер требует от вас явного имени каждого столбца в сводной таблице. Итак, следующий фрагмент вашего исходного запроса не разрешен:

for client_code in (select client_code from clients)

Вы должны были бы назвать каждый клиентский код явно.

Редактировать: Вот пример поворота, чтобы соответствовать вашему примеру:

WITH Permit (Usr, Client) AS
(
    SELECT 1, 'a' UNION ALL
    SELECT 1, 'b' UNION ALL
    SELECT 1, 'c' UNION ALL
    SELECT 2, 'a' UNION ALL
    SELECT 2, 'd' UNION ALL
    SELECT 3, 'a' UNION ALL
    SELECT 3, 'd' UNION ALL
    SELECT 3, 'e' UNION ALL
    SELECT 3, 'f'
)
SELECT p.*
FROM Permit
    PIVOT (MAX(Client) FOR Client IN (a, b, c, d, e, f)) p

Редактировать: вот опция динамического SQL; Вы могли бы поместить это в TVF:

--source table
CREATE TABLE #Permit (Usr int, Client char(1));
INSERT INTO #Permit (Usr, Client)
SELECT 1, 'a' UNION ALL
SELECT 1, 'b' UNION ALL
SELECT 1, 'c' UNION ALL
SELECT 2, 'a' UNION ALL
SELECT 2, 'd' UNION ALL
SELECT 3, 'a' UNION ALL
SELECT 3, 'd' UNION ALL
SELECT 3, 'e' UNION ALL
SELECT 3, 'f';


DECLARE @Command nvarchar(max);
SET @Command = '';

--prepare the list of columns
SELECT @Command = @Command + ', ' + CONVERT(nvarchar(10), Client)
FROM (SELECT DISTINCT Client FROM #Permit) x;

--chop the extra leading comma off
SET @Command = SUBSTRING(@Command, 3, LEN(@Command));

--prepare the rest of the pivot command
SET @Command = N'
SELECT p.*
FROM #Permit
    PIVOT (MAX(Client) FOR Client IN (' + @Command + ')) p';

--execute the command
EXEC sp_executesql @Command;


DROP TABLE #Permit;
...