TSQL 将行转换为列
Posted
技术标签:
【中文标题】TSQL 将行转换为列【英文标题】:TSQL turning rows to columns 【发布时间】:2018-05-30 11:38:08 【问题描述】:我有一个表 Items 具有以下结构:
code name price
001 item1 113
002 item2 90
003 item3 45
004 item4 47
我需要这样做:
code 001 002 003 004
name item1 item2 item3 item4
price 113 90 45 47
请问我该如何实现?
【问题讨论】:
在 T-SQL 中?不。使用您的表示层。您在那里混合了数据类型,因此在您的数据引擎中这样做更加不明智。 这是一个从存储过程调用的查询,后面没有应用程序 这是一个简单的查询,告诉我们你做了什么。 如果它是从 SP 调用的,而应用程序没有调用它,那是什么......? 会直接从SSMS调用 【参考方案1】:您可以使用PIVOT
和UNION
DECLARE @MyTable TABLE (code VARCHAR(10), name VARCHAR(10), price INT)
INSERT INTO @MyTable VALUES
('001','item1', 113),
('002','item2', 90 ),
('003','item3', 45 ),
('004','item4', 47 )
SELECT header as code, [001], [002], [003], [004] FROM (
SELECT 'name' header, code, name val FROM @MyTable
UNION ALL
SELECT 'price' header, code, CONVERT(VARCHAR(10),price) val FROM @MyTable
)SRC PIVOT( MAX(val) FOR code IN ( [001], [002], [003], [004])) PVT
结果:
code 001 002 003 004
----- ---------- ---------- ---------- ----------
name item1 item2 item3 item4
price 113 90 45 47
【讨论】:
【参考方案2】:@zineddine reda,试试下面的查询,你可以使用sql提供的pivot功能来完成
declare @Tbl table (code varchar(50), name varchar(50), Price int)
insert into @Tbl values ('001', 'item1', 113)
insert into @Tbl values ('002', 'item2', 90)
insert into @Tbl values ('003', 'item3', 45)
insert into @Tbl values ('004', 'item4', 47)
declare @Tbl1 table (ItemNAme nvarchar(50), ItemVal nvarchar(50))
insert into @Tbl1
Select 'Code',
STUFF((SELECT ', ' + Code
FROM @Tbl
FOR XML PATH('')), 1, 1, '')
from @Tbl
insert into @Tbl1
select 'Name',
STUFF((SELECT ', ' + name
FROM @Tbl
FOR XML PATH('')), 1, 1, '')
from @Tbl
insert into @Tbl1
select 'Price',
STUFF((SELECT ', ' + Convert(nvarchar(50),Price)
FROM @Tbl
FOR XML PATH('')), 1, 1, '')
from @Tbl
IF OBJECT_ID('tempdb..#Emp','U') IS NOT NULL DROP TABLE #Emp
SELECT E.*, P.Value AS ItemValue, 'ItemValue' + CONVERT(VARCHAR(10),P.ID) AS ItemValueID, P.ID AS ID
INTO #Emp
FROM @Tbl1 E OUTER APPLY dbo.fnSplit1(E.ItemVal,',') P
DECLARE @MaxID INT, @Cols VARCHAR(MAX), @SQL NVARCHAR(MAX), @i INT
SELECT @MaxID = MAX(ID) FROM #Emp
SET @i = 1
SET @Cols = ''
WHILE @i <=@MaxID
BEGIN
SET @Cols = @Cols + ', [ItemValue' + CONVERT(VARCHAR(10), @i) + ']'
SET @i = @i + 1
END
SET @Cols = RIGHT(@Cols, LEN(@Cols)-2)
print @Cols
SELECT @SQL = 'select ItemNAme, ' + @Cols + '
FROM (select ItemNAme, ItemVal, ItemValue, ItemValueID from #Emp) src
PIVOT (max(ItemValue) for ItemValueID IN (' + @Cols + '))pvt'
PRINT @SQL
EXECUTE (@SQL)
你的 fnSplit1 函数将是
CREATE FUNCTION [dbo].[FnSplit1]
(
@List nvarchar(2000),
@SplitOn nvarchar(5)
)
RETURNS @RtnValue table
(
Id int identity(1,1),
Value nvarchar(100)
)
AS
BEGIN
While (Charindex(@SplitOn,@List)>0)
Begin
Insert Into @RtnValue (value)
Select
Value = ltrim(rtrim(Substring(@List,1,Charindex(@SplitOn,@List)-1)))
Set @List = Substring(@List,Charindex(@SplitOn,@List)+len(@SplitOn),len(@List))
End
Insert Into @RtnValue (Value)
Select Value = ltrim(rtrim(@List))
Return
END
【讨论】:
我建议 Google 使用拆分功能。你的已经过时了以上是关于TSQL 将行转换为列的主要内容,如果未能解决你的问题,请参考以下文章