sqlserver - 使用 pivot 将多行合并为一行
sqlserver - combine multiple rows into one rows by using pivot
假设我们有以下 table:
ID Type Amount
0001 A 10
0001 B 20
0001 C 30
0002 A 15
0002 C 20
0003 B 40
...
期望的结果将是:
ID Type A Type B Type C
0001 10 20 30
为了将多行合并为一行,我可以执行以下操作。
SELECT ID, A, B, C
FROM MyTable
PIVOT
(
SUM(amount)
FOR Type IN (A, B, C)
) AS P
然而,我的 table 比前一个更复杂。
假设我的 table 如下:
ID Type Total_Amount Average_Amount
0001 A 10 0.5
0001 B 20 0.7
0001 C 30 0.9
所以我的问题是如何产生以下结果?
ID TypeA_total TypeB_total TypeC_total TypeA_avg TypeB_avg TypeC_avg
0001 10 20 30 0.5 0.7 0.9
更新:
类型数量固定。这意味着只有类型 A、B 和 C。
有些 ID 可能只有一种类型。有些可能具有所有 3 种类型。其他一些可能有2种。
Total_amount和Average_amount在原文中给出table。我不需要计算。
这里是 link,你可以用 table 玩:
http://sqlfiddle.com/#!3/4e6835
您需要unpivot
之前的数据pivoting
WITH cte
AS (SELECT id,
value,
col_name
FROM yourtable
CROSS apply( VALUES (total_amount,'Type' + type + '_Total'),
(average_amount,'Type' + type + '_Avg') )
CS (value, col_name))
SELECT *
FROM cte
PIVOT (Max(value)
FOR col_name IN([TypeA_total],[TypeB_total],[TypeC_total],
[TypeA_avg],[TypeB_avg],[TypeC_avg]))pv
注:如果没有。的 types
是未知的,那么你需要使用 dynamic sql
这是另一种方法。这是使用交叉表查询而不是 PIVOT。我发现语法不那么迟钝,甚至比使用 PIVOT 有轻微的性能提升。
if OBJECT_ID('tempdb..#something') is not null
drop table #something
create table #something
(
ID char(4)
, SomeType char(1)
, Amount int
, AverageAmount decimal(9, 2)
)
insert #something
select '0001', 'A', 10, .5 union all
select '0001', 'B', 20, .7 union all
select '0001', 'C', 30, .9;
with OrderedResults as
(
select *
, ROW_NUMBER() over(partition by ID order by SomeType) as RowNum
from #something
)
select ID
, MAX(Case when RowNum = 1 then SomeType end) as TypeA
, MAX(Case when RowNum = 1 then AverageAmount end) as AverageA
, MAX(Case when RowNum = 2 then SomeType end) as TypeB
, MAX(Case when RowNum = 2 then AverageAmount end) as AverageB
, MAX(Case when RowNum = 3 then SomeType end) as TypeC
, MAX(Case when RowNum = 3 then AverageAmount end) as AverageC
from OrderedResults
group by ID
假设我们有以下 table:
ID Type Amount
0001 A 10
0001 B 20
0001 C 30
0002 A 15
0002 C 20
0003 B 40
...
期望的结果将是:
ID Type A Type B Type C
0001 10 20 30
为了将多行合并为一行,我可以执行以下操作。
SELECT ID, A, B, C
FROM MyTable
PIVOT
(
SUM(amount)
FOR Type IN (A, B, C)
) AS P
然而,我的 table 比前一个更复杂。 假设我的 table 如下:
ID Type Total_Amount Average_Amount
0001 A 10 0.5
0001 B 20 0.7
0001 C 30 0.9
所以我的问题是如何产生以下结果?
ID TypeA_total TypeB_total TypeC_total TypeA_avg TypeB_avg TypeC_avg
0001 10 20 30 0.5 0.7 0.9
更新:
类型数量固定。这意味着只有类型 A、B 和 C。 有些 ID 可能只有一种类型。有些可能具有所有 3 种类型。其他一些可能有2种。
Total_amount和Average_amount在原文中给出table。我不需要计算。
这里是 link,你可以用 table 玩: http://sqlfiddle.com/#!3/4e6835
您需要unpivot
之前的数据pivoting
WITH cte
AS (SELECT id,
value,
col_name
FROM yourtable
CROSS apply( VALUES (total_amount,'Type' + type + '_Total'),
(average_amount,'Type' + type + '_Avg') )
CS (value, col_name))
SELECT *
FROM cte
PIVOT (Max(value)
FOR col_name IN([TypeA_total],[TypeB_total],[TypeC_total],
[TypeA_avg],[TypeB_avg],[TypeC_avg]))pv
注:如果没有。的 types
是未知的,那么你需要使用 dynamic sql
这是另一种方法。这是使用交叉表查询而不是 PIVOT。我发现语法不那么迟钝,甚至比使用 PIVOT 有轻微的性能提升。
if OBJECT_ID('tempdb..#something') is not null
drop table #something
create table #something
(
ID char(4)
, SomeType char(1)
, Amount int
, AverageAmount decimal(9, 2)
)
insert #something
select '0001', 'A', 10, .5 union all
select '0001', 'B', 20, .7 union all
select '0001', 'C', 30, .9;
with OrderedResults as
(
select *
, ROW_NUMBER() over(partition by ID order by SomeType) as RowNum
from #something
)
select ID
, MAX(Case when RowNum = 1 then SomeType end) as TypeA
, MAX(Case when RowNum = 1 then AverageAmount end) as AverageA
, MAX(Case when RowNum = 2 then SomeType end) as TypeB
, MAX(Case when RowNum = 2 then AverageAmount end) as AverageB
, MAX(Case when RowNum = 3 then SomeType end) as TypeC
, MAX(Case when RowNum = 3 then AverageAmount end) as AverageC
from OrderedResults
group by ID