使用 group by 动态将行转换为列
Dynamic convert Row to Column using group by
我正在寻找可以使用分组依据将行转列的代码,下面是我的 table 和想要的输出。
Table:
MR_ID | DR_ID
--------|--------
MR_123 | 1
MR_123 | 3
MR_124 | 4
MR_124 | 5
MR_124 | 6
MR_125 | 0
期望输出:
MR_ID | DR_ID_1 | DR_ID_2 | DR_ID_3
--------|----------|----------|---------
MR_123 | 1 | 2 | NULL
MR_124 | 4 | 5 | 6
MR_125 | 0 | NULL | NULL
这里我希望每个 DR_ID 的每个单独的列都有数字的增量,这应该是动态的。
这样试试:
DECLARE @mockup TABLE(MR_ID VARCHAR(10),DR_ID INT);
INSERT INTO @mockup VALUES
('MR_123',1)
,('MR_123',3)
,('MR_124',4)
,('MR_124',5)
,('MR_124',6)
,('MR_125',0);
SELECT p.*
FROM
(
SELECT *
,'DR_ID_' + CAST(ROW_NUMBER() OVER(PARTITION BY MR_ID ORDER BY DR_ID) AS VARCHAR(MAX)) AS columnName
FROM @mockup AS m
) AS t
PIVOT(MAX(DR_ID) FOR columnName IN(DR_ID_1,DR_ID_2,DR_ID_3,DR_ID_4)) AS p;
"dynamic column name" 是用 ROW_NUMBER()
创建的
您也可以使用动态 sql 查询。
查询
declare @sql as varchar(max);
select @sql = 'select t.MR_ID, ' + stuff((
select distinct ', max(case t.[rn] when '
+ cast(t.[rn] as varchar(10)) + ' then t.[DR_ID] end)
[DR_ID' + cast(t.[rn] as varchar(10)) + ']'
from (
select [rn] = row_number()
over(partition by MR_ID order by DR_ID), *
from your_table_name
)t
for xml path('')
), 1, 2, '')
+ ' from (select [rn] = row_number() over(partition by MR_ID order by DR_ID), *
from your_table_name)t
group by t.[MR_ID];';
exec(@sql);
试试这个,
create table #tmp (MR_ID varchar(50),DR_ID int)
insert into #tmp VALUES
('MR_123', 1),('MR_123', 3),('MR_124', 4),('MR_124', 5)
,('MR_124', 6),('MR_125', 0)
declare @DRCol varchar(50)
declare @Prefix varchar(20)='DR_'
;With CTE as
(
select *
,ROW_NUMBER()over(partition by MR_ID order by DR_ID)rn
from #tmp
)
select top 1
@DRCol=stuff((select ','+'['+@Prefix+cast(rn as varchar)+']'
from cte c1 where c.mr_id=c1.mr_id for xml path('')),1,1,'')
from cte c
where c.mr_id=(select top 1 mr_id from cte c1 order by rn desc)
declare @Sql varchar(2000)=''
set @Sql=' SELECT p.*
FROM
(
SELECT *
,'''+@Prefix+'''+ cast(ROW_NUMBER() OVER(PARTITION BY MR_ID ORDER BY DR_ID) as varchar(max)) columnName
FROM #tmp AS m
) AS t
PIVOT(MAX(DR_ID) FOR columnName IN('+@DRCol+')) AS p'
print @sql
exec(@sql)
drop table #tmp
我正在寻找可以使用分组依据将行转列的代码,下面是我的 table 和想要的输出。
Table:
MR_ID | DR_ID
--------|--------
MR_123 | 1
MR_123 | 3
MR_124 | 4
MR_124 | 5
MR_124 | 6
MR_125 | 0
期望输出:
MR_ID | DR_ID_1 | DR_ID_2 | DR_ID_3
--------|----------|----------|---------
MR_123 | 1 | 2 | NULL
MR_124 | 4 | 5 | 6
MR_125 | 0 | NULL | NULL
这里我希望每个 DR_ID 的每个单独的列都有数字的增量,这应该是动态的。
这样试试:
DECLARE @mockup TABLE(MR_ID VARCHAR(10),DR_ID INT);
INSERT INTO @mockup VALUES
('MR_123',1)
,('MR_123',3)
,('MR_124',4)
,('MR_124',5)
,('MR_124',6)
,('MR_125',0);
SELECT p.*
FROM
(
SELECT *
,'DR_ID_' + CAST(ROW_NUMBER() OVER(PARTITION BY MR_ID ORDER BY DR_ID) AS VARCHAR(MAX)) AS columnName
FROM @mockup AS m
) AS t
PIVOT(MAX(DR_ID) FOR columnName IN(DR_ID_1,DR_ID_2,DR_ID_3,DR_ID_4)) AS p;
"dynamic column name" 是用 ROW_NUMBER()
您也可以使用动态 sql 查询。
查询
declare @sql as varchar(max);
select @sql = 'select t.MR_ID, ' + stuff((
select distinct ', max(case t.[rn] when '
+ cast(t.[rn] as varchar(10)) + ' then t.[DR_ID] end)
[DR_ID' + cast(t.[rn] as varchar(10)) + ']'
from (
select [rn] = row_number()
over(partition by MR_ID order by DR_ID), *
from your_table_name
)t
for xml path('')
), 1, 2, '')
+ ' from (select [rn] = row_number() over(partition by MR_ID order by DR_ID), *
from your_table_name)t
group by t.[MR_ID];';
exec(@sql);
试试这个,
create table #tmp (MR_ID varchar(50),DR_ID int)
insert into #tmp VALUES
('MR_123', 1),('MR_123', 3),('MR_124', 4),('MR_124', 5)
,('MR_124', 6),('MR_125', 0)
declare @DRCol varchar(50)
declare @Prefix varchar(20)='DR_'
;With CTE as
(
select *
,ROW_NUMBER()over(partition by MR_ID order by DR_ID)rn
from #tmp
)
select top 1
@DRCol=stuff((select ','+'['+@Prefix+cast(rn as varchar)+']'
from cte c1 where c.mr_id=c1.mr_id for xml path('')),1,1,'')
from cte c
where c.mr_id=(select top 1 mr_id from cte c1 order by rn desc)
declare @Sql varchar(2000)=''
set @Sql=' SELECT p.*
FROM
(
SELECT *
,'''+@Prefix+'''+ cast(ROW_NUMBER() OVER(PARTITION BY MR_ID ORDER BY DR_ID) as varchar(max)) columnName
FROM #tmp AS m
) AS t
PIVOT(MAX(DR_ID) FOR columnName IN('+@DRCol+')) AS p'
print @sql
exec(@sql)
drop table #tmp