`
xiongzhenhui
  • 浏览: 209687 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

行轉列与列转行的使用(pivot与unpivot)

阅读更多

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_dateValue转换成的Column清单
 
2.UnPivot
--此段可以直接在Sql 2005中执行
CREATE TABLE pvt (VendorID int, Emp1 int, Emp2 int,
Emp3 int, Emp4 int, Emp5 int)
GO
INSERT 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], [Emp3], [Emp4], [Emp5])
)AS unpvt
GO

分享到:
评论

相关推荐

    Oracle行转列之pivot

    在Oracle数据库中,行转列(也称为数据透视)和列转行(unpivot)是SQL查询中用于数据转换的高级功能。从Oracle 11g版本开始,引入了PIVOT和UNPIVOT关键字,以支持显式的查询转换,即从行数据转换为列数据,或从列...

    access行转列示例

    在Access中,可以使用SQL的PIVOT函数或者通过创建交叉表查询来实现行转列。PIVOT函数允许用户指定原始数据中的行值作为新的列名,并对这些行值进行聚合计算。例如,假设我们有一个销售数据表,包含产品、地区和销售...

    Mysql 行转列,列转行 SQL语句和示例表结构SQL

    MySQL 提供了两种转换数据布局的方法:行转列(Pivot)和列转行(Unpivot),这在处理复杂的数据汇总和展示时非常有用。本文将深入探讨这两种转换方法,并提供具体的 SQL 语句示例,以及创建示例表结构的 SQL 代码。...

    sql行转列_列转行问题.

    除了使用`CASE WHEN`语句,SQL Server 2005及以后版本还提供了`PIVOT`和`UNPIVOT`两个运算符,使得行转列和列转行的操作更加简洁、高效。例如,在上述学生成绩表的场景中,使用`PIVOT`可以实现相同的行转列效果: `...

    行转列、列名转行

    除了PIVOT和UNPIVOT,还可以使用CASE语句和自连接等方法实现行转列和列名转行,尤其是在不支持这些操作的早期版本的SQL Server中。CASE语句适用于简单的转换,而自连接则适用于更复杂的转换,特别是当转换涉及多个值...

    SQL行列转换 Pivot UnPivot

    Pivot 语法的主要作用是将列值旋转为列名,即行转列。其基本语法为: ``` SELECT * FROM table_source PIVOT (聚合函数(value_column) FOR pivot_column IN ()) AS P; ``` 其中,聚合函数可以是 SUM、AVG、MAX、MIN ...

    mysql-行转列、列转行

    在数据库管理中,MySQL是一个广泛使用的开源关系型数据库系统,其功能强大且灵活。...总的来说,理解和掌握行转列与列转行的技巧,能够帮助我们更好地利用MySQL处理复杂的数据需求,提升数据分析和决策的效率。

    SQL知识点之列转行Unpivot函数

    与Pivot相反,Unpivot则是将列的数据转化为行,这样可以更容易地对单一属性的不同值进行分析。 在我们的例子中,我们有一个名为`dbo.CustomerPhones`的表,包含三个电话号码字段:`Phone1`、`Phone2`和`Phone3`,...

    oracle行转列

    - T-SQL_经典行专列、列转行,分页及存储过程.doc:T-SQL是SQL Server的扩展,但其中的行转列和分页概念与Oracle相似。在Oracle中,可以使用ROW_NUMBER()函数配合PARTITION BY和ORDER BY来实现分页查询。 - oracle_...

    Sql_Servcer行转列及列转行说明.docx

    行转列,即把数据库中的一行数据转换为多列显示,反之列转行则是将多列数据合并成一行。这里主要介绍的是使用`PIVOT`和`UNPIVOT`操作来实现这一目标。 `PIVOT`是SQL Server提供的一种关系运算符,它允许我们将一个...

    SQL行转列和列转行-静态互转-动态互转

    有case when方式和2005之后的内置pivot和unpivot方法来实现,行列互转,可以分为静态互转,动态互转。

    列转行小工具

    PIVOT用于将行数据转换为列,而UNPIVOT则相反,将列数据转换为行。下面将详细介绍这两种操作以及它们在实际应用中的使用场景。 1. PIVOT函数:当原始数据表中有多行重复的键值,但不同的列对应不同的值时,可以使用...

    sql 行专列 列转行 普通行列转换

    以下将详细探讨如何在SQL Server中进行行转列和列转行的操作。 1. **行转列(Pivot)** 行转列是将某一列的数据作为新表的列名,而其他列对应的数据则填充到这些新列中。在SQL Server中,可以使用`PIVOT`操作或`...

    Oracle的列转行问题

    列转行(Pivot)和行转列(Unpivot)是两种基本操作,可以将数据按照不同的维度进行组织。传统的列转行方法通常涉及`DECODE`或`CASE`函数与聚合函数如`MAX`或`MIN`的结合,但这些方法可能在处理大量数据时对性能造成...

    SQL行转列和列转行代码详解

    实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现。 在读了技术内幕那一节后,虽说这些解决方案早就用过了,却没有系统性的认识和总结过。为了加深认识,再总结一次。 行列互转,可以分为静态...

    SQLServer行列互转实现思路(聚合函数)

    总的来说,SQL Server的Pivot和Unpivot函数提供了强大的行转列和列转行功能,极大地简化了数据处理过程,使得复杂的数据分析变得更为便捷。通过熟练掌握这两个函数,可以提高我们在处理大数据时的效率和灵活性。对于...

    行列转换

    Pivot操作(列转行)用于将特定的行数据转换为列,而unpivot操作(行转列)则反之。 1. Pivot操作:Oracle提供了一种内建的PIVOT功能,允许用户将一组行数据转换为列。例如,假设有一个销售数据表,包含产品、年份...

    SQL行转列、列转行的简单实现

    在SQL数据库操作中,行转列和列转行是数据处理和分析中常见的需求,尤其在报表制作和数据展示时。这两种转换可以帮助我们更有效地组织和呈现数据。本篇文章将详细探讨MySQL中如何实现行转列和列转行的操作。 **行转...

Global site tag (gtag.js) - Google Analytics