2015-08-06 3 views
5

ExplainationPivot повторяющихся имен столбцов и получить все значения для столбцов

Представьте себе, что у меня есть 2 таблицы. FormFields где хранятся имена столбцов в качестве значений, которые должны быть повернуты, а вторая таблица FilledValues с заполненными значениями пользователя с FormFieldId.

ПРОБЛЕМА

Как вы видите (ниже в SAMPLE разделе) в FormFields таблице У меня есть повторяющиеся имена, но разные идентификаторы. Мне нужно сделать это после объединения таблиц, все значения из таблицы FilledValues будут приведены к именам столбцов, а не к идентификаторам.

Что мне нужно, вы увидите в OUTPUT ниже.

SAMPLE DATA

FormFields

ID Name GroupId 
1 col1  1 
2 col2  1 
3 col3  1 
4 col1  2 
5 col2  2 
6 col3  2 

FilledValues

ID Name FormFieldId GroupID 
1  a  2   1 
2  b  3   1 
3  c  1   1 
4  d  4   2 
5  e  6   2 
6  f  5   2 

ВЫВОД ПОКА

col1 col2 col3 
c  a  b -- As you see It returning only values for FormFieldId 1 2 3 
        -- d, e, f are lost that because It have duplicate col names, but different id's 

ХОЧЕТ ВЫХОДА

col1 col2 col3 
c  a  b 
e  f  d 

QUERY

SELECT * FROM 
(
    SELECT FF.Name AS NamePiv, 
      FV.Name AS Val1  
    FROM FormFields FF 
    JOIN FilledValues FV ON FF.Id = FV.FormFieldId  
) x 
PIVOT 
(
    MIN(Val1) 
    FOR NamePiv IN ([col1],[col2],[col3]) 
) piv 

SQL FIDDLE

Как я могу производить выход с несколькими строками?

ответ

2

Поскольку вы используете PIVOT данные были агрегированных, так что вы только вернуть одно значение для каждого столбца группируются. У вас нет столбцов в вашем подзапросе, которые уникальны и используются в аспекте группировки PIVOT, чтобы возвращать несколько строк. Для этого вам нужно какое-то значение. Если у вас есть столбец с уникальным значением для каждой «группы», то вы будете использовать его или можете использовать функцию окон, например row_number().

row_number() создаст секвенировал номер для каждого FF.Name значения, если у вас есть 2 col1 вы будете генерировать 1 для строки и 2 для другого ряда.После того, как это входит в ваш подзапроса, теперь у вас есть уникальное значение, которое используется при объединении данных, и вы будете возвращать несколько строк:

SELECT [col1],[col2],[col3] 
FROM 
(
    SELECT 
    FF.Name AS NamePiv, 
    FV.Name AS Val1, 
    rn = row_number() over(partition by ff.Name order by fv.Id) 
    FROM FormFields FF 
    JOIN FilledValues FV ON FF.Id = FV.FormFieldId   
) x 
PIVOT 
(
    MIN(Val1) 
    FOR NamePiv IN ([col1],[col2],[col3]) 
) piv; 

См SQL Fiddle with Demo. Выход:

| col1 | col2 | col3 | 
|------|------|------| 
| c | a | b | 
| e | f | d | 
+0

Спасибо за ответ, в некоторых «группах» есть небольшая проблема: все значения FormField пусты (без каких-либо значений), как я могу избежать выбора этих строк? Вот SQL Fiddle, добавленный GroupId 3 со всеми пустыми значениями. Эта строка не должна выбираться: http://sqlfiddle.com/#!3/2961a/1 –

+0

@ StanislovasKalašnikovas Используйте предложение where, чтобы отфильтровать пустые 'FilledValues' - http://sqlfiddle.com/#!3/2961a/3 – Taryn

2

Просто добавить GroupId в Pivot source запрос будет исправить вашу проблему

SELECT * FROM (
SELECT FF.Name AS NamePiv, 
     FV.Name AS Val1, 
     ff.groupid 
FROM FormFields FF 
JOIN FilledValues FV ON FF.Id = FV.FormFieldId  
) x 
PIVOT 
(
MIN(Val1) 
FOR NamePiv IN ([col1],[col2],[col3]) 
) piv 

SQLFIDDLE DEMO

+0

Спасибо за ответ, в некоторых «группах» есть небольшая проблема: все значения FormField пусты (без каких-либо значений), как я могу избежать выбора этих строк? Вот SQL Fiddle, добавленный GroupId 3 со всеми пустыми значениями. Эта строка не должна выбираться: http://sqlfiddle.com/#!3/2961a/1 –

+0

@ StanislovasKalašnikovas - Простой фильтр должен исправить эту проблему http://sqlfiddle.com/#!3/2961a/2 или на основе по требованию продлить фильтр –

0

я был бы склонен сделать это с условной агрегации:

select max(case when formfieldid % 3 = 1 then name end) as col1, 
     max(case when formfieldid % 3 = 2 then name end) as col2, 
     max(case when formfieldid % 3 = 0 then name end) as col3 
from FilledValues 
group by GroupID; 

Пока неясно, что это правило для присвоения значения в столбце. Это использует остаток, который работает для ваших входных данных.

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