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】:

您可以使用PIVOTUNION

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 将行转换为列的主要内容,如果未能解决你的问题,请参考以下文章

将行转换为列

将行数据转换为列

pyspark 将行转换为列

使用R将行转换为列,将列转换为行

不能从子查询将行转换为列

将行转换为列