我在SQL中有3列 - 名称,ID和句点:
Name CarID Period
---------------------
Bob 121 Jan 08
Bob 123 Jan 08
Bob 121 Feb 08
Steve 121 Jan 08
Ruth 139 Feb 08
我需要将CarID与唯一名称和期间一起转动,即:
Name Period Col1 Col2 Col3
-------------------------------------
Bob Jan 08 121 123 NULL
Bob Feb 08 121 NULL NULL
Steve Jan 08 121 NULL NULL
Ruth Feb 08 139 NULL NULL
我的问题是,指定用户的名字可能有1或x个CarID。我已经尝试了一些动态数据透视查询,但他们都必须设置列标题名称。
答案 0 :(得分:1)
有几种方法可以获得所需的结果,但为了成功返回每个carid
和name
的多个period
值,我会使用窗口函数与row_number()
类似,可为name
/ period
的每个分区生成唯一序列。
您的查询将从使用以下内容开始:
select name, carid, period,
'col'+
cast(row_number() over(partition by name, period
order by carid) as varchar(10)) seq
from yourtable;
见SQL Fiddle with Demo。这将为您提供以下数据,然后您可以将其PIVOT到列中。
| NAME | CARID | PERIOD | SEQ |
|-------|-------|--------|------|
| Bob | 121 | Feb 08 | col1 |
| Bob | 121 | Jan 08 | col1 |
| Bob | 123 | Jan 08 | col2 |
| Ruth | 139 | Feb 08 | col1 |
| Steve | 121 | Jan 08 | col1 |
然后,您可以使用聚合函数和类似于:
的CASE表达式将此数据转换为列select
name,
period,
max(case when seq = 'col1' then carid end) col1,
max(case when seq = 'col2' then carid end) col2,
max(case when seq = 'col3' then carid end) col3
from
(
select name, carid, period,
'col'+
cast(row_number() over(partition by name, period
order by carid) as varchar(10)) seq
from yourtable
) d
group by name, period;
见SQL Fiddle with Demo。也可以使用PIVOT
函数将其转换为列:
select name, period, col1, col2, col3
from
(
select name, carid, period,
'col'+
cast(row_number() over(partition by name, period
order by carid) as varchar(10)) seq
from yourtable
) d
pivot
(
max(carid)
for seq in (col1, col2, col3)
) p;
见SQL Fiddle with Demo。如果您的值有限,上述两个查询将很有用,但如果您有未知值,则必须使用动态SQL生成结果:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(seq)
from
(
select 'col'+
cast(row_number() over(partition by name, period
order by carid) as varchar(10)) seq
from yourtable
) d
group by seq
order by seq
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT name, period,' + @cols + '
from
(
select name, carid, period,
''col''+
cast(row_number() over(partition by name, period
order by carid) as varchar(10)) seq
from yourtable
) x
pivot
(
max(carid)
for seq in (' + @cols + ')
) p '
execute sp_executesql @query;
见SQL Fiddle with Demo。所有版本都会给你一个类似于:
的结果| NAME | PERIOD | COL1 | COL2 |
|-------|--------|------|--------|
| Bob | Feb 08 | 121 | (null) |
| Ruth | Feb 08 | 139 | (null) |
| Bob | Jan 08 | 121 | 123 |
| Steve | Jan 08 | 121 | (null) |