Cee*_*Vei 1 sql-server pivot unpivot
我已经尝试了Pivot,Unpivot交叉表周围的所有可能性 - 你的名字.
斗争是因为我已经完成了这项工作.我希望它能成为一个简单的解决方案,因为我无法看到它.
我很抱歉没有提供DDL.
但基本上我有一个看起来像这样的表.
DeptName Metric1_Name Metric1_Value Metric2_Name Metric2_Value Metric3_Name Metric3_Value Metric4_Name Metric4_Value
ABC Sales Per Hour 200 Wins Per Hour 10 Leads per Hour 2 Losses per Hour 1
ABC Sales per Minute 20 Wins per Minute 1 Leads per minute 1 Losses per Minute 1
XYZ Sales Per Hour 5000 Wins Per Hour 300 Leads per Hour 20 Losses per Hour 10
XYZ Sales per Minute 2000 Wins per Minute 100 Leads per minute 10 Losses per Minute 10
Run Code Online (Sandbox Code Playgroud)
我希望得到这样的结果
DeptName Sales per Hour Sales per minute Wins Per Hour Wins per Minute Leads per Hour Leads per minute Losses per Hour Losses per Minute
ABC 200 20 10 1 2 1 1 1
XYZ 5000 2000 300 100 20 10 10 10
Run Code Online (Sandbox Code Playgroud)
我正在使用SQL-Server 2012.但我想解决方案可以在2008 R2上运行
捕获 - 1)名为Metric1_name等的列数未知.有人可以添加metric_36,我将在13天内不知道.
2)有超过1个字段,如DeptName,我相信可以省略这个例子.一旦有人给我指示如何解决它我会添加它们.
我非常感谢你花时间帮助我.
干杯
Tar*_*ryn 10
首先,我强烈建议您重新设计当前的结构.您当前的结构未规范化,并且难以维护,尤其是如果您允许用户向表中添加新列.在我解释如何使用当前结构获得结果之前,我将演示如果重新设计表格会更容易.
新表设计: 这是关于如何将表重写为更灵活的工作模型的建议.如果您有以下表格和示例数据:
-- contains the names of each metric you need to track
CREATE TABLE metric
(
[id] int,
[name] varchar(17)
);
INSERT INTO metric ([id], [name])
VALUES (1, 'Sales per Hour'), (2, 'Sales per Minute'),
(3, 'Wins per Hour'), (4, 'Wins per Minute'),
(5, 'Leads per Hour'), (6, 'Leads per Minute'),
(7, 'Losses per Hour'), (8, 'Losses per Minute');
-- contains the details of your departments
CREATE TABLE Departments
(
[id] int,
[name] varchar(3)
);
INSERT INTO Departments ([id], [name])
VALUES (1, 'ABC'), (2, 'XYZ');
-- associates the dept to each metric and the value
CREATE TABLE details
(
[deptid] int,
[metricid] int,
[value] int
);
INSERT INTO details ([deptid], [metricid], [value])
VALUES
(1, 1, 200), (1, 2, 20), (1, 3, 10),
(1, 4, 1), (1, 5, 2), (1, 6, 1),
(1, 7, 1), (1, 8, 1), (2, 1, 5000),
(2, 2, 2000), (2, 3, 300), (2, 4, 100),
(2, 5, 20), (2, 6, 10), (2, 7, 10),
(2, 8, 10);
Run Code Online (Sandbox Code Playgroud)
此设计更加灵活,因为您可以轻松添加新指标以进行跟踪,而无需向表中添加新列.这甚至可以扩展为为捕获值的每一天添加日期/时间列.您可以使用以下方法轻松加入:
select d.name deptname, m.name, dt.value
from departments d
inner join details dt
on d.id = dt.deptid
inner join metric m
on dt.metricid = m.id;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.这将为您提供每个部门的所有指标以及相关的值,然后可以使用pivot将其转换为列:
select deptname,
[Sales per hour], [Sales per minute],
[Wins per hour], [Wins per minute],
[Leads per hour], [Leads per minute],
[Losses per hour], [Losses per minute]
from
(
select d.name deptname, m.name, dt.value
from departments d
inner join details dt
on d.id = dt.deptid
inner join metric m
on dt.metricid = m.id
) src
pivot
(
max(value)
for name in ([Sales per hour], [Sales per minute],
[Wins per hour], [Wins per minute],
[Leads per hour], [Leads per minute],
[Losses per hour], [Losses per minute])
) piv;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.如果您有未知的度量标准类型,则可以轻松地将上述查询转换为动态SQL.
使用现有表:您可以通过首先取消列,然后应用PIVOT函数来获得结果.我建议使用CROSS APPLYunivot数据,这样你就可以将多列成对转换成行.取消使用的语法CROSS APPLY是:
select deptname, name, value
from yourtable
cross apply
(
values
(Metric1_Name, Metric1_Value),
(Metric2_Name, Metric2_Value),
(Metric3_Name, Metric3_Value),
(Metric4_Name, Metric4_Value)
) c (name, value)
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.这会将您的数据转换为以下格式:
| DEPTNAME | NAME | VALUE |
|----------|-------------------|-------|
| ABC | Sales Per Hour | 200 |
| ABC | Wins Per Hour | 10 |
| ABC | Leads per Hour | 2 |
| ABC | Losses per Hour | 1 |
| ABC | Sales per Minute | 20 |
| ABC | Wins per Minute | 1 |
| ABC | Leads per minute | 1 |
| ABC | Losses per Minute | 1 |
Run Code Online (Sandbox Code Playgroud)
一旦数据采用这种格式,您就可以轻松应用PIVOT功能.如果您的值有限,以下内容将起作用:
select deptname,
[Sales per hour], [Sales per minute],
[Wins per hour], [Wins per minute],
[Leads per hour], [Leads per minute],
[Losses per hour], [Losses per minute]
from
(
select deptname, name, value
from yourtable
cross apply
(
values
(Metric1_Name, Metric1_Value),
(Metric2_Name, Metric2_Value),
(Metric3_Name, Metric3_Value),
(Metric4_Name, Metric4_Value)
) c (name, value)
) d
pivot
(
max(value)
for name in ([Sales per hour], [Sales per minute],
[Wins per hour], [Wins per minute],
[Leads per hour], [Leads per minute],
[Losses per hour], [Losses per minute])
) piv
order by deptname;
Run Code Online (Sandbox Code Playgroud)
由于您当前的表结构,如果您具有未知值,这将变得更加复杂,但以下动态SQL脚本应该为您提供所需的结果:
DECLARE @colsUnpivotList AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@colsPivot as NVARCHAR(MAX),
@q nvarchar(max)
declare @temp table
(
name varchar(50),
pos int
) ;
-- create the list of columns for the cross apply
select @colsUnpivotList
= stuff((select ', ('+quotename('Metric'+CAST(seq as varchar(2))+nm)
+ ', '+quotename('Metric'+CAST(seq as varchar(2))+vl) +')'
from
(
select distinct substring(C.COLUMN_NAME, 7, CHARINDEX('_', c.column_name)-7) seq
from INFORMATION_SCHEMA.columns as C
where C.TABLE_NAME = 'yourtable'
and C.COLUMN_NAME not in ('DeptName')
) s
cross join
(
select '_Name', '_Value'
) c (nm, vl)
for xml path('')), 1, 1, '')
-- create a sql string to get the list of values to be pivoted
select @q = stuff((select 'union select '+c.COLUMN_NAME + ' nm, '+ cast(c.ordinal_position as varchar(10))+' pos from yourtable '
from INFORMATION_SCHEMA.columns as C
where C.TABLE_NAME = 'yourtable'
and C.COLUMN_NAME not in ('DeptName')
and C.COLUMN_NAME like ('%_Name')
for xml path('')), 1, 6, '')
insert into @temp execute(@q );
-- use the @temp table to get the list of values to pivot
select @colsPivot = STUFF((SELECT ',' + quotename(name)
from @temp
group by name, pos
order by pos
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT deptname, ' + @colsPivot + '
from
(
select deptname, name, value
from yourtable
cross apply
(
values
'+@colsUnpivotList +'
) c (name, value)
) x
pivot
(
max(value)
for name in (' + @colsPivot + ')
) p '
execute sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.所有版本都得到结果:
| DEPTNAME | SALES PER HOUR | SALES PER MINUTE | WINS PER HOUR | WINS PER MINUTE | LEADS PER HOUR | LEADS PER MINUTE | LOSSES PER HOUR | LOSSES PER MINUTE |
|----------|----------------|------------------|---------------|-----------------|----------------|------------------|-----------------|-------------------|
| ABC | 200 | 20 | 10 | 1 | 2 | 1 | 1 | 1 |
| XYZ | 5000 | 2000 | 300 | 100 | 20 | 10 | 10 | 10 |
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1380 次 |
| 最近记录: |