听起来您需要先对数据进行反透视,然后再对数据进行透视。如果您有未知数量的值,您将不得不使用动态 SQL,但我建议首先编写查询的硬代码或静态版本,然后将其转换为动态 SQL。
取消透视数据的过程将包含多列tableB
并将其转换为多行。由于您使用的是 SQL Server 2012,因此您可以使用 CROSS APPLY 来取消透视数据:
select column1, column2, column3,
col = col + '_' + cast(seq as varchar(10)),
value
from
(
select a.column1, a.column2, a.column3,
b.column6, b.column7, b.column8,
row_number() over(partition by a.column1
order by a.column1) seq
from tablea a
inner join tableb b
on a.column1 = b.column6
) d
cross apply
(
select 'column6', column6 union all
select 'column7', column7 union all
select 'column8', column8
) c (col, value);
请参阅SQL Fiddle with Demo。这将为您提供类似于以下的结果:
| COLUMN1 | COLUMN2 | COLUMN3 | COL | VALUE |
| 1 | 2 | 3 | column6_1 | 1 |
| 1 | 2 | 3 | column7_1 | 18 |
| 1 | 2 | 3 | column8_1 | 56 |
| 1 | 2 | 3 | column6_2 | 1 |
| 1 | 2 | 3 | column7_2 | 25 |
| 1 | 2 | 3 | column8_2 | 89 |
如您所见,您现在有多个行,您可以轻松地将数据透视函数应用于这些行。PIVOT 代码将是:
select column1, column2, column3,
column6_1, column7_1, column8_1,
column6_2, column7_2, column8_2,
column6_3, column7_3, column8_3
from
(
select column1, column2, column3,
col = col + '_' + cast(seq as varchar(10)),
value
from
(
select a.column1, a.column2, a.column3,
b.column6, b.column7, b.column8,
row_number() over(partition by a.column1
order by a.column1) seq
from tablea a
inner join tableb b
on a.column1 = b.column6
) d
cross apply
(
select 'column6', column6 union all
select 'column7', column7 union all
select 'column8', column8
) c (col, value)
) src
pivot
(
max(value)
for col in (column6_1, column7_1, column8_1,
column6_2, column7_2, column8_2,
column6_3, column7_3, column8_3)
) piv;
请参阅SQL Fiddle with Demo。由于您声明您可能有未知或动态数量的条目,tableB
您将需要使用动态 SQL。这将生成一个 sql 字符串,该字符串将被执行以获得最终结果:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(col +'_'+cast(seq as varchar(10)))
from
(
select row_number() over(partition by column6
order by column6) seq
from tableB
) t
cross apply
(
select 'column6', 1 union all
select 'column7', 2 union all
select 'column8', 3
) c (col, so)
group by col, so, seq
order by seq, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT column1, column2, column3,' + @cols + '
from
(
select column1, column2, column3,
col = col + ''_'' + cast(seq as varchar(10)),
value
from
(
select a.column1, a.column2, a.column3,
b.column6, b.column7, b.column8,
row_number() over(partition by a.column1
order by a.column1) seq
from tablea a
inner join tableb b
on a.column1 = b.column6
) d
cross apply
(
select ''column6'', column6 union all
select ''column7'', column7 union all
select ''column8'', column8
) c (col, value)
) x
pivot
(
max(value)
for col in (' + @cols + ')
) p '
execute sp_executesql @query;
请参阅SQL Fiddle with Demo。两个版本都给出了结果:
| COLUMN1 | COLUMN2 | COLUMN3 | COLUMN6_1 | COLUMN7_1 | COLUMN8_1 | COLUMN6_2 | COLUMN7_2 | COLUMN8_2 | COLUMN6_3 | COLUMN7_3 | COLUMN8_3 |
| 1 | 2 | 3 | 1 | 18 | 56 | 1 | 25 | 89 | (null) | (null) | (null) |
| 2 | 4 | 6 | 2 | 78 | 245 | (null) | (null) | (null) | (null) | (null) | (null) |
| 3 | 8 | 9 | 3 | 10 | 15 | 3 | 45 | 457 | 3 | 89 | 50 |