主要應用case語句來解決行轉列的問題
行轉列問題主要分為兩類
1)簡單的行轉列問題:
樣本表:
id sid course result
1 2005001 語文 80.0
2 2005001 數學 90.0
3 2005001 英語 80.0
4 2005002 語文 56.0
5 2005002 數學 69.0
6 2005002 英語 89.0
執行
select sid,語文=isnull(sum(case course when '語文' then result end),0),
數學=isnull(sum(case course when '數學' then result end),0),
英語=isnull(sum(case course when '英語' then result end),0)
from result
group by sid
order by sid
得出結果
sid 語文 數學 英語
2005001 80.0 90.0 80.0
2005002 56.0 69.0 89.0
2)較為複雜的行轉列
表1:course
id name
1 語文
2 數學
3 英語
表2:result
id sid course result
1 2005001 語文 80.0
2 2005001 數學 90.0
3 2005001 英語 80.0
4 2005002 語文 56.0
5 2005002 數學 69.0
6 2005002 英語 89.0
declare @sql varchar(8000)
set @sql='select sid'
select @sql=@sql+','+course.name+'=isnull(sum(case course when '''+course.name+''' then result end),0)'
from course order by id
set @sql=@sql+' from result group by sid order by sid'
print @sql
exec(@sql)
得出結果
sid 語文 數學 英語
2005001 80.0 90.0 80.0
2005002 56.0 69.0 89.0
-----------------列轉行---------------------------------------------------------------------------------------------------------
有字串'1,2,3,4,5,,6,7,8,'這樣的不定長字串,要求將其轉成一列N行來儲存,也就是列轉行,哪種方式最快.
經過討論,下列方式最快.
declare @var varchar(8000)
,@sql varchar(8000)
,@last varchar(1)
,@ctrl int
set @var='1,2,3,4,5,,6,7,'
set @ctrl=0
while @ctrl=0
begin
if (select charindex(',,',@var))>0
select @var=replace(@var,',,',',')
else
set @ctrl=1
end
set @last=right(@var,1)
if @last=','
set @var=left(@var,len(@var)-1)
set @sql='select '+replace(@var,',',' union all select '
-------------------------------------------------可啟動並執行------------------------------------
--交叉表語句的實現:
CREATE TABLE Test
(
id int IDENTITY(1,1) NOT NULL,
name nvarchar(50) NULL,
subject nvarchar(50) NULL,
Source numeric(18,0) NULL
)
GO
INSERT INTO [test] ([name],[subject],[Source]) values (N'張三',N'語文',60)
INSERT INTO [test] ([name],[subject],[Source]) values (N'李四',N'數學',70)
INSERT INTO [test] ([name],[subject],[Source]) values (N'王五',N'英語',80)
INSERT INTO [test] ([name],[subject],[Source]) values (N'王五',N'數學',75)
INSERT INTO [test] ([name],[subject],[Source]) values (N'王五',N'語文',57)
INSERT INTO [test] ([name],[subject],[Source]) values (N'李四',N'語文',80)
INSERT INTO [test] ([name],[subject],[Source]) values (N'張三',N'英語',100)
Go
SELECT * FROM TEST
--用於:交叉表的列數是確定的
select name,sum(case subject when '數學' then source else 0 end) as '數學',
sum(case subject when '英語' then source else 0 end) as '英語',
sum(case subject when '語文' then source else 0 end) as '語文'
from test
group by name
--用於:交叉表的列數是不確定的
declare @sql varchar(8000)
set @sql = 'select name'
select @sql = @sql + ',sum(case subject when '''+subject+'''
then source else 0 end) as '''+subject+''' '
from (select distinct subject from test) as a
select @sql = @sql + ' from test group by name'
exec(@sql)