CHill60
Я разберу ваш вопрос по разделам ... во-первых
Цитата:
(1), я не знаю, что делать с агрегатной функцией, так как мне нечего агрегировать
Как я уже сказал в своем комментарии, если агрегировать нечего, то я обычно использую
MAX()
(или
MIN()
Это имеет чистый эффект просто возвращения значения, которое вы хотите. Вот вам пример:
SELECT [foreign_key], [plant], [clothing], [country], [continent], [vehicle], [season]
FROM
(
SELECT row_id, foreign_key, Field_Name, field_value
FROM my_source_table
) a
PIVOT
(
MAX(field_value)
FOR Field_Name IN ([plant],[clothing],[country],[continent],[vehicle],[season] )
) AS pvt
ORDER BY foreign_key
Примечание в вашей попытке вы использовали
FOR vehicle IN ...
Колонка [транспортное средство] фактически не существует до тех пор, пока не будет задействована ось, поэтому вы не можете ссылаться на нее в теле оси. Вы также не хотите этого делать, вы преобразуете значения [Field_Name] в столбцы, так что это то, что должно быть включено в это предложение.
К сожалению, запрос в его нынешнем виде приводит к таким бесполезным результатам...
foreign_key plant clothing country continent vehicle season
1 flower NULL NULL NULL NULL NULL
1 NULL pants NULL NULL NULL NULL
1 NULL NULL usa NULL NULL NULL
1 NULL NULL NULL NULL NULL spring
2 tree NULL NULL NULL NULL NULL
2 NULL NULL NULL europe NULL NULL
2 NULL NULL france NULL NULL NULL
3 flower NULL NULL NULL NULL NULL
3 NULL NULL brazil NULL NULL NULL
3 NULL NULL NULL NULL bike NULL
3 NULL NULL NULL NULL NULL summer
Нам нужно каким-то образом их объединить ... например
SELECT [foreign_key], MAX([plant]) AS [plant], MAX([clothing]) as [clothing], MAX([country]) as [country], MAX([continent]) as [continent], MAX([vehicle]) as [vehicle], MAX([season]) as [season]
FROM
(
SELECT row_id, foreign_key, Field_Name, field_value
FROM my_source_table
) a
PIVOT
(
MAX(field_value)
FOR Field_Name IN ([plant],[clothing],[country],[continent],[vehicle],[season] )
) AS pvt
GROUP BY foreign_key
ORDER BY foreign_key
Обратите внимание, что я делаю агрегат на наборе данных, созданном PIVOT, "а также" агрегат в pivot. Это приводит к вашим ожидаемым результатам
foreign_key plant clothing country continent vehicle season
1 flower pants usa NULL NULL spring
2 tree NULL france europe NULL NULL
3 flower NULL brazil NULL bike summer
Цитата:
(2), я не знаю, как определить заголовки столбцов динамически, основываясь на различных значениях в таблице my_source_table.колонки имя_поля
Для этого вам нужно сгенерировать некоторый динамический SQL. Давайте посмотрим на первый бит, который может измениться в зависимости от данных...сначала давайте добавим некоторые дополнительные данные
insert into my_source_table (foreign_key, Field_Name, field_value) values (1, 'sense', 'smell')
Таким образом, мы знаем, что нам придется "построить" что-то, что добавляет это новое значение к биту SQL, который в настоящее время говорит
SELECT [foreign_key], [plant], [clothing], [country], [continent], [vehicle], [season]
Есть несколько способов построения этого списка - потому что я хочу добавить несколько квадратных скобок, это, вероятно, самый простой
DECLARE @liststr NVARCHAR(MAX) = null
;WITH fieldValues AS
(
SELECT DISTINCT Field_Name FROM my_source_table
)
SELECT @liststr = COALESCE(@liststr +'],[','') + Field_Name
FROM fieldValues
SELECT '[' + @liststr + ']'
Это даст свои результаты
[clothing],[continent],[country],[plant],[season],[sense],[vehicle]
Обратите внимание, что я не могу контролировать порядок, в котором они возвращаются, если только я не заказываю по запросу. Этот порядок должен быть вне CTE ... то есть. Я не могу этого сделать
SELECT DISTINCT Field_Name FROM my_source_table ORDER BY Field_Name
Я должен использовать
FROM fieldValues ORDER BY Field_Name
Также обратите внимание, что переменная начинается как null, и я должен добавить недостающую скобку в конце. Дайте ему попробовать другой способ, чтобы понять, почему.
Теперь давайте обратимся к другому биту, который должен измениться теперь, когда мы добавили новые данные, - сказал исходный запрос
SELECT [foreign_key], MAX([plant]) AS [plant], MAX([clothing]) as [clothing], MAX([country]) as [country], MAX([continent]) as [continent], MAX([vehicle]) as [vehicle], MAX([season]) as [season]
Это немного более неудобно, так как мне нужно дважды обратиться к имени Поля и включить функцию MAX. Хорошенько посмотрите на разницу в том, как я это делаю. Также обратите внимание, что я хочу игнорировать первые два символа, когда использую результаты
DECLARE @liststr2 NVARCHAR(MAX) = null
;WITH MAXfieldValues AS
(
SELECT DISTINCT Field_Name, Field_Name AS FN FROM my_source_table
)
SELECT @liststr2 = COALESCE(@liststr2,'') +'],MAX([' + Field_Name + ']) AS [' + Field_Name
FROM MAXfieldValues ORDER BY Field_Name
SELECT SUBSTRING(@liststr2,3, LEN(@liststr2)) + ']'
Это приводит к результатам
MAX([clothing]) AS [clothing],MAX([continent]) AS [continent],MAX([country]) AS [country],MAX([plant]) AS [plant],MAX([season]) AS [season],MAX([sense]) AS [sense],MAX([vehicle]) AS [vehicle]
Мы уже знаем, как должна выглядеть остальная часть запроса, поэтому давайте сошьем все вместе и запустим его
DECLARE @sql NVARCHAR(MAX) = N'SELECT [foreign_key], ' + SUBSTRING(@liststr2,3, LEN(@liststr2)) + ']' +
' FROM
(
SELECT row_id, foreign_key, Field_Name, field_value
FROM my_source_table
) a
PIVOT
(
MAX(field_value)
FOR Field_Name IN ([' + @liststr + '] )) AS pvt
GROUP BY foreign_key
ORDER BY foreign_key'
Exec sp_executesql @sql
И результаты тоже...
FK clothing continent country plant season sense vehicle
1 pants NULL usa flower spring smell NULL
2 NULL europe france tree NULL NULL NULL
3 NULL NULL brazil flower summer NULL bike
Я действительно призываю вас проработать различные разделы, чтобы убедиться, что вы полностью понимаете, что происходит. Есть ссылки на документацию и другие примеры в статье ссылка в моем комментарии