旋转重复的列名并获取列的所有值
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
如何生成包含多行的输出?
只需在 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
由于您使用的是 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;
不清楚为列赋值的规则是什么。这使用余数,适用于您的输入数据。
解释
假设我有 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
如何生成包含多行的输出?
只需在 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
由于您使用的是 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;
不清楚为列赋值的规则是什么。这使用余数,适用于您的输入数据。