1. 程式人生 > >在論壇中出現的比較難的sql問題:39(動態行轉列 動態日期列問題)

在論壇中出現的比較難的sql問題:39(動態行轉列 動態日期列問題)

最近,在論壇中,遇到了不少比較難的sql問題,雖然自己都能解決,但發現過幾天后,就記不起來了,也忘記解決的方法了。

所以,覺得有必要記錄下來,這樣以後再次碰到這類問題,也能從中獲取解答的思路。

求一SQL語句。

create table #tab 
(
col1 char(10),
col2 char(10),
item char(10),
num int,
[Date] varchar(10))
insert #tab values('AAA','BBB','A',50,'2013-06-10')
insert #tab values('ABB','BGG','B',30,'2013-06-10')
insert #tab values('AAA','BBB','C',80,'2013-06-13')

我的解法:

create table tab 
(
col1 char(10),
col2 char(10),
item char(10),
num int,
[Date] varchar(10)
)

insert tab values('AAA','BBB','A',50,'2013-06-10')
insert tab values('ABB','BGG','B',30,'2013-06-10')
insert tab values('AAA','BBB','C',80,'2013-06-13')




--動態生成sql語句
declare @start_date varchar(10) = '2013-06-01',
        @end_date   varchar(10) = '2013-06-30';

declare @date  varchar(10),
        @sql   varchar(max) = '',
        @sql1  varchar(8000),
        @sql2  varchar(8000);

set @date = @start_date;

set @sql1 = 'select case when rownum = 1 then col1 else '''' end as col1,
                    case when rownum = 1 then col2 else '''' end as col2,
                    item'

set @sql2 = 'select col1,col2,item,row_number() over(partition by col1,col2 
                                                         order by item) as rownum'
        

while @date <= @end_date
begin
    set @sql1 = @sql1 + ',v_' + REPLACE( right(@date,5),'-','') + 
                        ' as ''' + CAST(DATEPART(month,@date) as varchar) + '/' +
                                 CAST(DATEPART(day,@date) as varchar) +'''';                                  
	set @sql2 = @sql2 + ',SUM(case when date =''' + @date + 
	                   ''' then num else 0 end) as v_' + 
	                   REPLACE( right(@date,5),'-','')
	
	set @date = CONVERT(varchar(10),dateadd(day,1,@date),120)
end


set @sql = @sql1 + ' from (' +
                       @sql2 + ' from tab 
                                 group by col1,col2,item' +
                   ') v'
 
--生產的動態sql語句                  
select @sql


exec(@sql)


上面由於是動態生成語句,所以不能用區域性的臨時表,所以建了一個表。

下面是動態生成的sql語句,經過了格式化:

select case when rownum = 1 then col1 else '' end as col1,
       case when rownum = 1 then col2 else '' end as col2,                     
       item,
       
       v_0601 as '6/1',v_0602 as '6/2',v_0603 as '6/3',
       v_0604 as '6/4',v_0605 as '6/5',
       v_0606 as '6/6',v_0607 as '6/7',
       v_0608 as '6/8',v_0609 as '6/9',
       v_0610 as '6/10',v_0611 as '6/11',
       v_0612 as '6/12',v_0613 as '6/13',
       v_0614 as '6/14',v_0615 as '6/15',
       v_0616 as '6/16',v_0617 as '6/17',
       v_0618 as '6/18',v_0619 as '6/19',
       v_0620 as '6/20',v_0621 as '6/21',
       v_0622 as '6/22',v_0623 as '6/23',
       v_0624 as '6/24',v_0625 as '6/25',
       v_0626 as '6/26',v_0627 as '6/27',
       v_0628 as '6/28',v_0629 as '6/29',
       v_0630 as '6/30' 
from 
(
	select col1,col2,item,
	
		   row_number() over(partition by col1,col2  order by item) as rownum,
		   
		   SUM(case when date ='2013-06-01' then num else 0 end) as v_0601,
		   SUM(case when date ='2013-06-02' then num else 0 end) as v_0602,
		   SUM(case when date ='2013-06-03' then num else 0 end) as v_0603,
		   SUM(case when date ='2013-06-04' then num else 0 end) as v_0604,
		   SUM(case when date ='2013-06-05' then num else 0 end) as v_0605,
		   SUM(case when date ='2013-06-06' then num else 0 end) as v_0606,
		   SUM(case when date ='2013-06-07' then num else 0 end) as v_0607,
		   SUM(case when date ='2013-06-08' then num else 0 end) as v_0608,
		   SUM(case when date ='2013-06-09' then num else 0 end) as v_0609,
		   SUM(case when date ='2013-06-10' then num else 0 end) as v_0610,
		   SUM(case when date ='2013-06-11' then num else 0 end) as v_0611,
		   SUM(case when date ='2013-06-12' then num else 0 end) as v_0612,
		   SUM(case when date ='2013-06-13' then num else 0 end) as v_0613,
		   SUM(case when date ='2013-06-14' then num else 0 end) as v_0614,
		   SUM(case when date ='2013-06-15' then num else 0 end) as v_0615,
		   SUM(case when date ='2013-06-16' then num else 0 end) as v_0616,
		   SUM(case when date ='2013-06-17' then num else 0 end) as v_0617,
		   SUM(case when date ='2013-06-18' then num else 0 end) as v_0618,
		   SUM(case when date ='2013-06-19' then num else 0 end) as v_0619,
		   SUM(case when date ='2013-06-20' then num else 0 end) as v_0620,
		   SUM(case when date ='2013-06-21' then num else 0 end) as v_0621,
		   SUM(case when date ='2013-06-22' then num else 0 end) as v_0622,
		   SUM(case when date ='2013-06-23' then num else 0 end) as v_0623,
		   SUM(case when date ='2013-06-24' then num else 0 end) as v_0624,
		   SUM(case when date ='2013-06-25' then num else 0 end) as v_0625,
		   SUM(case when date ='2013-06-26' then num else 0 end) as v_0626,
		   SUM(case when date ='2013-06-27' then num else 0 end) as v_0627,
		   SUM(case when date ='2013-06-28' then num else 0 end) as v_0628,
		   SUM(case when date ='2013-06-29' then num else 0 end) as v_0629,
		   SUM(case when date ='2013-06-30' then num else 0 end) as v_0630 
	from tab                                    
	group by col1,col2,item
) v