根据 SQL 中的分组列对列进行透视值
Pivot values on column based on grouped columns in SQL
我想根据组将值转换为列。但是,我事先不知道这些值。
一个查询给了我这个结果。
Id Code EntityId
----------- ------------ -------------
3 22209776 1
4 143687971 3
4 143687971 4
4 143687971 5
4 143687971 15
5 143658155 7
5 143658155 8
我要输出这个
Id Code EntityId1 EntityId2 EntityId3 EntityId4
----------- ------------ ------------- ------------- ------------- -------------
3 22209776 1 NULL NULL NULL
4 143687971 3 4 5 15
5 143658155 7 8 NULL NULL
您可以尝试使用枢轴函数:
declare @tmp TABLE (id int, Code int, EntityId NVARCHAR(10))
insert into @tmp (id, Code, EntityId)
values (3, 22209776 , 1),
(4, 143687971, 3),
(4, 143687971, 4),
(4, 143687971, 5),
(4, 143687971, 15),
(5, 143658155, 7),
(5, 143658155, 8)
select
pvt.id
,pvt.Code
,[1] as EntityID1
,[2] as EntityID2
,[3] as EntityID3
,[4] as EntityID4
from (
select
id, Code, EntityId
,ROW_NUMBER() over(partition by code order by EntityId) as RowNum
from
@tmp
) a
pivot (MAX(EntityId) for RowNum in ([1], [2], [3], [4])) as pvt
如果您现在知道结果中有多少列,则需要使用动态 T-SQL 语句来构建 PIVOT
。例如:
IF OBJECT_ID('tempdb..#DataSource') IS NOT NULL
BEGIN;
DROP TABLE #DataSource;
END;
CREATE TABLE #DataSource
(
[id] INT
,[Code] INT
,[EntityId] INT
);
DECLARE @DynamicTSQLStatement NVARCHAR(MAX)
,@Columns NVARCHAR(MAX);
DECLARE @MaxColumns INT;
INSERT INTO #DataSource ([id], [Code], [EntityId])
VALUES (3, 22209776 , 1)
,(4, 143687971, 3)
,(4, 143687971, 4)
,(4, 143687971, 5)
,(4, 143687971, 15)
,(5, 143658155, 7)
,(5, 143658155, 8)
,(4, 143687971, 25)
,(4, 143687971, 26);
-- we need to know how many columns are going to be shown
SELECT TOP 1 @MaxColumns = COUNT(*)
FROM #DataSource
GROUP BY [Code]
ORDER BY COUNT(*) DESC;
-- we are building here the following string '[1],[2],[3],[4],[5],[6]';
-- this will change depending the input data
WITH gen AS
(
SELECT 1 AS num
UNION ALL
SELECT num+1
FROM gen
WHERE num+1<=@MaxColumns
)
SELECT @Columns = STUFF
(
(
SELECT ',[EntityId' + CAST([num] AS VARCHAR(12)) + ']'
FROM gen
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)')
,1
,1
,''
)
OPTION (maxrecursion 10000);
SET @DynamicTSQLStatement = N'
SELECT *
FROM
(
SELECT [id]
,[Code]
,[EntityId]
,''EntityId'' + CAST(ROW_NUMBER() OVER(PARTITION BY [Code] ORDER BY [EntityId]) AS VARCHAR(12))
FROM #DataSource
) DS ([id], [Code], [EntityId], [RowID])
PIVOT
(
MAX([EntityId]) for [RowID] in (' + @Columns +')
) PVT;';
EXEC sp_executesql @DynamicTSQLStatement;
我想根据组将值转换为列。但是,我事先不知道这些值。
一个查询给了我这个结果。
Id Code EntityId
----------- ------------ -------------
3 22209776 1
4 143687971 3
4 143687971 4
4 143687971 5
4 143687971 15
5 143658155 7
5 143658155 8
我要输出这个
Id Code EntityId1 EntityId2 EntityId3 EntityId4
----------- ------------ ------------- ------------- ------------- -------------
3 22209776 1 NULL NULL NULL
4 143687971 3 4 5 15
5 143658155 7 8 NULL NULL
您可以尝试使用枢轴函数:
declare @tmp TABLE (id int, Code int, EntityId NVARCHAR(10))
insert into @tmp (id, Code, EntityId)
values (3, 22209776 , 1),
(4, 143687971, 3),
(4, 143687971, 4),
(4, 143687971, 5),
(4, 143687971, 15),
(5, 143658155, 7),
(5, 143658155, 8)
select
pvt.id
,pvt.Code
,[1] as EntityID1
,[2] as EntityID2
,[3] as EntityID3
,[4] as EntityID4
from (
select
id, Code, EntityId
,ROW_NUMBER() over(partition by code order by EntityId) as RowNum
from
@tmp
) a
pivot (MAX(EntityId) for RowNum in ([1], [2], [3], [4])) as pvt
如果您现在知道结果中有多少列,则需要使用动态 T-SQL 语句来构建 PIVOT
。例如:
IF OBJECT_ID('tempdb..#DataSource') IS NOT NULL
BEGIN;
DROP TABLE #DataSource;
END;
CREATE TABLE #DataSource
(
[id] INT
,[Code] INT
,[EntityId] INT
);
DECLARE @DynamicTSQLStatement NVARCHAR(MAX)
,@Columns NVARCHAR(MAX);
DECLARE @MaxColumns INT;
INSERT INTO #DataSource ([id], [Code], [EntityId])
VALUES (3, 22209776 , 1)
,(4, 143687971, 3)
,(4, 143687971, 4)
,(4, 143687971, 5)
,(4, 143687971, 15)
,(5, 143658155, 7)
,(5, 143658155, 8)
,(4, 143687971, 25)
,(4, 143687971, 26);
-- we need to know how many columns are going to be shown
SELECT TOP 1 @MaxColumns = COUNT(*)
FROM #DataSource
GROUP BY [Code]
ORDER BY COUNT(*) DESC;
-- we are building here the following string '[1],[2],[3],[4],[5],[6]';
-- this will change depending the input data
WITH gen AS
(
SELECT 1 AS num
UNION ALL
SELECT num+1
FROM gen
WHERE num+1<=@MaxColumns
)
SELECT @Columns = STUFF
(
(
SELECT ',[EntityId' + CAST([num] AS VARCHAR(12)) + ']'
FROM gen
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)')
,1
,1
,''
)
OPTION (maxrecursion 10000);
SET @DynamicTSQLStatement = N'
SELECT *
FROM
(
SELECT [id]
,[Code]
,[EntityId]
,''EntityId'' + CAST(ROW_NUMBER() OVER(PARTITION BY [Code] ORDER BY [EntityId]) AS VARCHAR(12))
FROM #DataSource
) DS ([id], [Code], [EntityId], [RowID])
PIVOT
(
MAX([EntityId]) for [RowID] in (' + @Columns +')
) PVT;';
EXEC sp_executesql @DynamicTSQLStatement;