1.使用pivot進行報表的行轉列 收藏
行轉列在報表中是用的很多的,以前在sql中使用橫轉列的時候總是使用selet case來處理,即便sql2005現在都要被sql2008代替了,偶還一次沒有用過他提供的新東東pivot。一時興起,還是學了學。
有兩個簡化的表(**商表和供貨記錄表)
create table supplier (sid int,suppliershortname varchar(20))--記錄**商的簡稱和**
create table warehouserecord (sid int,materialid int,qty numeric(18,2),price numeric(18,4),billdate smalldatetime)--記錄每天**商的送貨記錄
管理需求上下面這個是經常遇到的,需要知道最近乙個月或一周內每個**商的供貨情況,可能需要得到的表樣式是下面的
日期 **商a供貨金額 **商b供貨金額 **商c供貨金額 .....
2008-11-25 300.2 250.0 2562.65
我們建立好錶後填入記錄,開始下面的工作
--寫入**商記錄
insert into supplier (sid,suppliershortname) select 1,'**商a'
insert into supplier (sid,suppliershortname) select 2,'**商b'
insert into supplier (sid,suppliershortname) select 3,'**商c'
--送貨記錄
insert into warehouserecord (sid,materialid,qty,price,billdate) select 1,10000,200,5.4,'2008-11-25'
insert into warehouserecord (sid,materialid,qty,price,billdate) select 2,11000,30,95.4,'2008-11-25'
insert into warehouserecord (sid,materialid,qty,price,billdate) select 1,15000,50,6.32,'2008-11-25'
insert into warehouserecord (sid,materialid,qty,price,billdate) select 3,11000,220,9.2,'2008-11-25'
要達到我們需要的效果,如果還是使用sql 2000中的方式我們也很容易
select c.billdate,
sum(case when c.suppliershortname='**商a' then c.qty*c.price else 0 end) as **商a,
sum(case when c.suppliershortname='**商b' then c.qty*c.price else 0 end) as **商b,
sum(case when c.suppliershortname='**商c' then c.qty*c.price else 0 end) as **商c
from (select a.suppliershortname,b.* from supplier a,warehouserecord b where a.sid=b.sid) c group by c.billdate
這樣就可以得到我們的結果了,如果**商比較多,是不是有點長了。
寫完了sql2000的,現在如果換成了sql2005的pivot,則是如何寫的呢?
select billdate,[**商a],[**商b],[**商c] from
(select a.suppliershortname,sum(b.qty*b.price) as daymoney,b.billdate from supplier a,warehouserecord b where a.sid=b.sid group by b.billdate,a.suppliershortname) c
pivot (sum(daymoney) for suppliershortname in ([**商a],[**商b],[**商c])) as unpvt
看起來好像只是語句短了點,其他的差別不大吧。
上面兩種方法寫的都是固定欄位的,如果**商很多,或者要監控的**商是一直變化的,按上面那樣方法寫還不死人啊。
對於不固定列的,sql2000是如何寫的呢?
declare @sql varchar(8000)
set @sql = 'select billdate '
select @sql = @sql + ' , sum(case c.suppliershortname when ''' + suppliershortname + ''' then c.price*c.qty else 0 end) [' + suppliershortname + ']'
from (select distinct suppliershortname from supplier) as a
set @sql = @sql + ' from (select a.suppliershortname,b.* from supplier a,warehouserecord b where a.sid=b.sid) c group by c.billdate'
exec(@sql)
執行的結果就和上面的一樣了。
那麼使用sql2005提供的新方法pivot又是如何寫的呢?
declare @selstr varchar(1000)
declare @sql varchar(8000)
select @selstr = isnull(@selstr + ',','')+ '['+ltrim(suppliershortname)+']'
from (select suppliershortname from supplier) d
set @sql='select billdate,'+@selstr+' from (select a.suppliershortname,b.billdate,sum(b.qty*b.price) as daymoney from supplier a,warehouserecord b where a.sid=b.sid group by b.billdate,a.suppliershortname) c '
set @sql=@sql+'pivot (sum(daymoney) for suppliershortname in ('+@selstr+')) as unpvt'
print @sql
exec(@sql)
感覺出差別來了沒有?
說真的,就自己的感覺,我還是覺得以前的方法比較好理解一點。也許人總是活著習慣中,當你習慣一種方法時,改變是真的有點困難,除非你努力將新方法成為了你新的習慣。
2..pivot的用法體會:
語句範例:
select pn,[2006/5/30] as [20060530],[2006/6/2] as [20060602]
from consumptiondata a
pivot (sum(a.m_qty) for a.m_date in ([2006/5/30],[2006/6/2])) as pvt
order by pn
table結構 consumptiondata (pn,m_date,m_qty)
order by pn可要可不要,並不重要,只是排序的作用
關鍵的是紅色部分,解析如下,select 大家都知道,pn是 consumptiondata表中的乙個column,
[2006/5/30]也是乙個column,他需要顯示成[20060530],注意[2006/5/30]不是乙個value,而是乙個column.[2006/6/2]與[2006/5/30]一樣.
pivot ( ........... ) as pvt這個結構是固定格式,沒有什麼需要特殊說明的,當然pvt隨便你給他乙個nickname ,it doesn't make any differences.
sum(a.m_qty) 是我們希望顯示出來的值,注意這個地方必須用彙總函式,否則語法不會過.
for a.m_date in ([2006/5/30],[2006/6/2])
for 表示彙總的值要顯示在哪乙個column下面
如果我們想讓sum(m_qty)顯示在pn轉換的column下面,則可寫為for pn, in 的清單表示我們關注哪些要檢視的column,注意再次強調是column,不是value. in的清單是column清單,不是value清單,是m_date的value轉換成的column清單.
2.unpivot
--此段可以直接在sql 2005中執行
create table pvt (vendorid int, emp1 int, emp2 int,
e*** int, emp4 int, emp5 int)
goinsert into pvt values (1,4,3,5,4,4)
insert into pvt values (2,4,1,5,5,5)
insert into pvt values (3,4,3,5,4,4)
insert into pvt values (4,4,2,5,5,4)
insert into pvt values (5,5,1,5,5,5)
go --select * from pvt
--unpivot the table.
select vendorid, employee, orders
from pvt
unpivot (
orders for employee in ([emp1], [emp2], [e***], [emp4], [emp5])
)as unpvt
go
行轉列 列轉行
行轉列 select t.t.rowid from test1 t id c1 c2 c3 1 小紅 數學 10 2 小紅 語文 20 3 小欄 數學 15 4 小欄 語文 25 test1 oracle select c1,to char wm concat c2 c2 from test1 gr...
Oracle 行轉列與列轉行
oracel 行轉列與列轉行 一 列轉行 1.使用函式 wm concat 2.函式說明 該函式將某一列,根據條件轉換成一行 相當於把列裡的值合併,並用逗號區分各個值 3.例子 表 testt 中有資料如下所示 xh age 1 11 1 12 1 13 2 21 2 22 3 31 sql sel...
MySQL行轉列與列轉行
建表 新增資料 create table test tb grade id int 10 not null auto increment,user name varchar 20 default null,course varchar 20 default null,score float defa...