旋转重复的列名并获取列的所有值

Pivot duplicate column names and get all values for columns

解释

假设我有 2 个 table。 FormFields 其中存储的列名作为值,应该进行旋转,第二个 table FilledValues 包含用户填充的值,提供 FormFieldId

问题

正如您在 FormFields table 中看到的(在下面 SAMPLE 部分 ),我有重复的名字,但 ID 不同。我需要在加入 tables 之后,将来自 FilledValues table 的所有值分配给列名,而不是 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 

查询

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

如何生成包含多行的输出?

只需在 Pivot source 查询中添加 GroupId 即可解决您的问题

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

由于您使用的是 PIVOT,因此数据正在聚合,因此您只需 return 为每一列分组一个值。您的子查询中没有任何列是唯一的,并且没有在 PIVOT 的分组方面使用到 return 多行。为了做到这一点,你需要一些价值。如果你有一个列,每个 "group" 都有一个唯一值,那么你可以使用它,或者你可以使用像 row_number() 这样的窗口函数。

row_number() 将为每个 FF.Name 创建一个序列号,这意味着如果你有 2 col1 你将为一行生成一个 1 和一个 2 换一行。一旦将其包含在您的子查询中,您现在就有了一个在聚合数据时使用的唯一值,您将 return 多行:

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 |

我倾向于使用条件聚合来做到这一点:

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;

不清楚为列赋值的规则是什么。这使用余数,适用于您的输入数据。