我正在尝试找出将多列枚举为两行的最佳方法。例如,下面的数据包含公司中每个职位的汇总员工数,按全职等效(FTE)状态划分。
+---------------+--------------+-------------------------+------+------+------+------+------+------+------+
| Position | PositionSlot | PositionSlotDescrpition | PD | P5 | P6 | P7 | P8 | P9 | FT |
+---------------+--------------+-------------------------+------+------+------+------+------+------+------+
| 1-400400-0680 | NULL | NULL | 7 | 1 | 2 | NULL | 1 | 18 | NULL |
| 1-400400-0041 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 1 |
| 1-400400-0660 | NULL | NULL | NULL | NULL | NULL | NULL | 1 | 6 | NULL |
+---------------+--------------+-------------------------+------+------+------+------+------+------+------+
因此,对于Position 1-400400-0680
,上面列出了29名员工。
我需要枚举这些聚合,为每个PositionSlot
创建一个顺序 Position
,与FTE突破相关。
Position
的总行数应等于列PD, P5, P6, P7, P8, P9, and FT
的总和。 PositionsSlotDescription
应为原始列名PD, P5, P6, P7, P8, P9, and FT
PositionSlot
应该是这些行的顺序编号。 广告位的排序无关紧要。因此PositionSlot = 1
可以属于任何PositionsSlotDescription
PositionsSlotDescription
/
根据原始聚合中的数字重复。例如,Position 1-400400-0660
的{{1}}为1,P8
为6。因此,应该有1行P9
PositionSlotDescription
和6行P8
PositionSlotDescription
,P9
应该是1-7 < / p>
预期成果
PositionSlots
TEST SCRIPTS
+---------------+--------------+-------------------------+
| Position | PositionSlot | PositionSlotDescrpition |
+---------------+--------------+-------------------------+
| 1-400400-0041 | 1 | FT |
| 1-400400-0660 | 1 | P8 |
| 1-400400-0660 | 2 | P9 |
| 1-400400-0660 | 3 | P9 |
| 1-400400-0660 | 4 | P9 |
| 1-400400-0660 | 5 | P9 |
| 1-400400-0660 | 6 | P9 |
| 1-400400-0660 | 7 | P9 |
| 1-400400-0680 | 1 | P5 |
| 1-400400-0680 | 2 | P6 |
| 1-400400-0680 | 3 | P6 |
| 1-400400-0680 | 4 | P8 |
| 1-400400-0680 | 5 | P9 |
| 1-400400-0680 | 6 | P9 |
| 1-400400-0680 | 7 | P9 |
| 1-400400-0680 | 8 | P9 |
| 1-400400-0680 | 9 | P9 |
| 1-400400-0680 | 10 | P9 |
| 1-400400-0680 | 11 | P9 |
| 1-400400-0680 | 12 | P9 |
| 1-400400-0680 | 13 | P9 |
| 1-400400-0680 | 14 | P9 |
| 1-400400-0680 | 15 | P9 |
| 1-400400-0680 | 16 | P9 |
| 1-400400-0680 | 17 | P9 |
| 1-400400-0680 | 18 | P9 |
| 1-400400-0680 | 19 | P9 |
| 1-400400-0680 | 20 | P9 |
| 1-400400-0680 | 21 | P9 |
| 1-400400-0680 | 22 | P9 |
| 1-400400-0680 | 23 | PD |
| 1-400400-0680 | 24 | PD |
| 1-400400-0680 | 25 | PD |
| 1-400400-0680 | 26 | PD |
| 1-400400-0680 | 27 | PD |
| 1-400400-0680 | 28 | PD |
| 1-400400-0680 | 29 | PD |
+---------------+--------------+-------------------------+
答案 0 :(得分:3)
使用adhoc数字表和cross apply(values ...)
来取消数据的显示:
;with numbers as (
select top (32) --<-- 32 works for the example, increase for larger sets
i=row_number() over(order by (select 1))
from master..spt_values
order by i
)
select
t.Position
, PositionSlot=row_number() over (
partition by t.Position
order by v.PositionSlotDescription, n.i
)
, v.PositionSlotDescription
from @table t
cross apply (values
('PD',PD),('P5',P5) ,('P6',P6) ,('P7',P7) ,('P8',P8) ,('P9',P9) ,('FT',FT)
) v (PositionSlotDescription, Amount)
inner join numbers n
on n.i <= v.amount
where v.Amount is not null
order by t.Position, v.PositionSlotDescription
rextester演示:http://rextester.com/AMKCR70455
返回:
+---------------+--------------+-------------------------+
| Position | PositionSlot | PositionSlotDescription |
+---------------+--------------+-------------------------+
| 1-400400-0041 | 1 | FT |
| 1-400400-0660 | 1 | P8 |
| 1-400400-0660 | 2 | P9 |
| 1-400400-0660 | 3 | P9 |
| 1-400400-0660 | 4 | P9 |
| 1-400400-0660 | 5 | P9 |
| 1-400400-0660 | 6 | P9 |
| 1-400400-0660 | 7 | P9 |
| 1-400400-0680 | 1 | P5 |
| 1-400400-0680 | 2 | P6 |
| 1-400400-0680 | 3 | P6 |
| 1-400400-0680 | 4 | P8 |
| 1-400400-0680 | 5 | P9 |
| 1-400400-0680 | 6 | P9 |
| 1-400400-0680 | 7 | P9 |
| 1-400400-0680 | 8 | P9 |
| 1-400400-0680 | 9 | P9 |
| 1-400400-0680 | 10 | P9 |
| 1-400400-0680 | 11 | P9 |
| 1-400400-0680 | 12 | P9 |
| 1-400400-0680 | 13 | P9 |
| 1-400400-0680 | 14 | P9 |
| 1-400400-0680 | 15 | P9 |
| 1-400400-0680 | 16 | P9 |
| 1-400400-0680 | 17 | P9 |
| 1-400400-0680 | 18 | P9 |
| 1-400400-0680 | 19 | P9 |
| 1-400400-0680 | 20 | P9 |
| 1-400400-0680 | 21 | P9 |
| 1-400400-0680 | 22 | P9 |
| 1-400400-0680 | 23 | PD |
| 1-400400-0680 | 24 | PD |
| 1-400400-0680 | 25 | PD |
| 1-400400-0680 | 26 | PD |
| 1-400400-0680 | 27 | PD |
| 1-400400-0680 | 28 | PD |
| 1-400400-0680 | 29 | PD |
+---------------+--------------+-------------------------+
参考:
<小时/> 对于较大的集合,您可以将
cross join from master..spt_values
添加到上面的number
cte,或将numbers
cte替换为此替代堆叠的cte:
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, numbers as (
select top(50000)
i=row_number() over (order by (select 1))
from n as deka cross join n as hecto cross join n as kilo
cross join n as tenK cross join n as hundredK
)
rextester演示:http://rextester.com/OZZHR43374
答案 1 :(得分:0)
包含UNPIVOT
和递归CTE
--Unpivot results
if object_id('tempdb..#unpivot') is not null drop table #unpivot
select
u.Position
,u.Code
,u.Descr
into #unpivot
from
@table t
unpivot
(
code
for Descr in (PD, P5, P6, P7, P8, P9, FT)
) u
--Recursive CTE
;with cte as(
select
t.Position
,Code = 1
,t.Descr
from #unpivot t
union all
select
t2.Position
,cte.Code + 1
,t2.Descr
from #unpivot t2
inner join cte
on cte.Position = t2.Position
and cte.Descr = t2.Descr
where t2.Code > cte.Code)
--Results
select
Position
--,Code
,PositionSlotCode = row_number() over (partition by Position order by Descr)
,Descr
from
cte
order by
Position
,Descr
,Code