透视重复的列名称并获取列的所有值

时间:2015-08-06 13:41:04

标签: sql sql-server sql-server-2008 tsql pivot

想象一下,我有2张桌子。 FormFields其中将列名称存储为值,应将其存档,并将第二个表FilledValues与用户填充的值FormFieldId一起提供。

问题

正如您在FormFields表中看到的(在 SAMPLE部分中),我有重复的名称,但ID不同。我需要在连接表之后进行此操作,FilledValues表中的所有值都将被分配到列名,而不是Id。

我需要的更好,您将在下面的 OUTPUT 部分看到。

示例数据

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

如何生成多行的OUTPUT?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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; 另一排。一旦它包含在您的子查询中,您现在拥有一个在汇总数据时使用的唯一值,您将返回多行:

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

SQL Fiddle with Demo。输出是:

void setValues(int, int, string);

void myClass::setValues(int yrs, int lbs, string clr)
{
    this -> age = yrs;
    this -> weight = lbs;
    this -> color = clr;
}

答案 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;

目前还不清楚为列分配值的规则是什么。这使用余数,它适用于您的输入数据。