Версии данных SQL Server 2008 по горизонтали
Извиняюсь за отправку другого вопроса по этой теме, но я прочитал многие ответы на это, и я не могу заставить его работать для меня.
У меня есть три таблицы, в которые мне нужно присоединиться и вывести информацию. Одна из таблиц состоит из 3 столбцов и сохраняет данные по вертикали. Я хотел бы перенести данные в горизонтальный формат.
Данные будут выглядеть так, если я просто присоединяюсь и вытягиваю:
SELECT
a.app_id,
b.field_id,
c.field_name,
b.field_value
FROM table1 a
JOIN table2 b ON a.app_id = b.app_id
JOIN table3 c ON b.field_id = c.field_id --(table3 is a lookup table for field names)
Результат:
app_id | field_id | field_name | field_value
-----------------------------------------------------
1234 | 101 | First Name | Joe
1234 | 102 | Last Name | Smith
1234 | 105 | DOB | 10/15/72
1234 | 107 | Mailing Addr | PO BOX 1234
1234 | 110 | Zip | 12345
1239 | 101 | First Name | Bob
1239 | 102 | Last Name | Johnson
1239 | 105 | DOB | 12/01/78
1239 | 107 | Mailing Addr | 1234 N Star Ave
1239 | 110 | Zip | 12456
Вместо этого я хотел бы, чтобы он выглядел так:
app_id | First Name | Last Name | DOB | Mailing Addr | Zip
--------------------------------------------------------------------------
1234 | Joe | Smith | 10/15/72 | PO BOX 1234 | 12345
1239 | Bob | Johnson | 12/01/78 | 1234 N Star Ave | 12456
В прошлом я просто прибегал к поиску всего поля, который мне нужен в моих данных, и создавал операторы CASE для каждого из них. Приложение, которое пользователи используют, содержит данные для нескольких продуктов, и каждый продукт содержит разные поля. Учитывая количество поддерживаемых продуктов и количество полей для каждого продукта (многие, многие из которых больше, чем основной пример, показанный выше), требуется много времени, чтобы просмотреть их и выписать огромные куски операторов CASE.
Мне было интересно, есть ли там чит-код для достижения того, что мне нужно, не имея необходимости искать полевые_иды и писать вещи. Я знаю, что функция PIVOT, вероятно, то, что я ищу, однако, я не могу заставить ее работать правильно.
Думаете, вы, ребята, могли помочь?
Ответы
Ответ 1
Вы можете использовать функцию PIVOT для преобразования ваших строк данных в столбцы.
Ваш исходный запрос может быть использован для извлечения всех данных, единственное изменение, которое я сделал бы для него, - исключить столбец b.field_id
, потому что это изменит окончательное отображение результата.
Если у вас есть известный список значений field_name
, которые вы хотите включить в столбцы, вы можете запрограммировать свой запрос:
select app_id,
[First Name], [Last Name], [DOB],
[Mailing Addr], [Zip]
from
(
SELECT
a.app_id,
c.field_name,
b.field_value
FROM table1 a
INNER JOIN table2 b
ON a.app_id = b.app_id
INNER JOIN table3 c
ON b.field_id = c.field_id
) d
pivot
(
max(field_value)
for field_name in ([First Name], [Last Name], [DOB],
[Mailing Addr], [Zip])
) piv;
Смотрите SQL Fiddle with Demo.
Но если у вас будет неизвестное количество значений для field_name
, вам нужно будет реализовать динамический SQL, чтобы получить результат:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(Field_name)
from Table3
group by field_name, Field_id
order by Field_id
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT app_id,' + @cols + '
from
(
SELECT
a.app_id,
c.field_name,
b.field_value
FROM table1 a
INNER JOIN table2 b
ON a.app_id = b.app_id
INNER JOIN table3 c
ON b.field_id = c.field_id
) x
pivot
(
max(field_value)
for field_name in (' + @cols + ')
) p '
execute sp_executesql @query;
См. SQL Fiddle with Demo. Оба эти результата приведут к результату:
| APP_ID | FIRST NAME | LAST NAME | DOB | MAILING ADDR | ZIP |
------------------------------------------------------------------------
| 1234 | Joe | Smith | 10/15/72 | PO Box 1234 | 12345 |
| 1239 | Bob | Johnson | 12/01/78 | 1234 N Star Ave | 12456 |
Ответ 2
Попробуйте это
SELECT
[app_id]
,MAX([First Name]) AS [First Name]
,MAX([Last Name]) AS [Last Name]
,MAX([DOB]) AS [DOB]
,MAX([Mailing Addr]) AS [Mailing Addr]
,MAX([Zip]) AS [Zip]
FROM Table1
PIVOT
(
MAX([field_value]) FOR [field_name] IN ([First Name],[Last Name],[DOB],[Mailing Addr],[Zip])
) T
GROUP BY [app_id]
SQL FIDDLE DEMO
Ответ 3
bluefeet ответ был правильным для меня, но мне нужно было выделить в списке столбцов:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT Distinct ',' + QUOTENAME(Field_name)
from Table3
group by field_name, Field_id
order by ',' + QUOTENAME(Field_name)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT app_id,' + @cols + '
from
(
SELECT
a.app_id,
c.field_name,
b.field_value
FROM table1 a
INNER JOIN table2 b
ON a.app_id = b.app_id
INNER JOIN table3 c
ON b.field_id = c.field_id
) x
pivot
(
max(field_value)
for field_name in (' + @cols + ')
) p '
execute sp_executesql @query;