设为首页 加入收藏

TOP

锋利的SQL-SQLServer的表旋转(行列转换)(一)
2014-11-24 02:54:41 来源: 作者: 【 】 浏览:9
Tags:锋利 SQL-SQLServer 旋转 行列 转换

所谓表旋转,就是将表的行转换为列,或是将表的列转换为行,这是从SQL Server 2005开始提供的新技术。因此,如果希望使用此功能,需要将数据库的兼容级别设置为90。表旋转在某些方面也是解决了表的数据存储和实际需要之间的矛盾。例如,图9-4所示的是一个典型的产品销售统计表,这种格式虽然便于阅读,但是在进行数据表存储的时候却并不容易管理,产品销售数据表通常需要设计成图9-5所示的结构。这样就带来一个问题,用户既希望数据容易管理,又希望能够生成一种能够容易阅读的表格数据,这时候就可以使用表旋转技术。

\

图9-4 产品销售表

\

图9-5 数据表结构

9.4.1 PIVOT运算符

PIVOT运算符用于将表的行转换为列,并能同时对行执行聚合运算。其语法格式如下:

SELECT <非旋转列>,

[第一个旋转列] AS <列名>,

[第二个旋转列] AS <列名>, < http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD48cD4gICAgLi4uIDwvcD48cD4gICAgW9fuuvO1xND916rB0F0gQVMgJmx0O8HQw/smZ3Q7IDwvcD48cD5GUk9NIDwvcD48cD4gICAgKCZsdDtTRUxFQ1Qgyfqzycr9vt21xLLp0a8mZ3Q7KSBBUyAmbHQ7zqrUtLLp0a+94bn71ri2qLXEsfDD+yZndDs8L3A+PHA+IDwvcD48cD5QSVZPVCA8L3A+PHA+KCA8L3A+PHA+ICAgICZsdDu+27rPuq/K/SZndDsoJmx0O7G7vtu6z7XEwdAmZ3Q7KSA8L3A+PHA+Rk9SIDwvcD48cD5bJmx0O7D8uqy9q7G716q7u86qwdCx6s23tcTWtbXEwdAmZ3Q7XSA8L3A+PHA+ICAgIElOICggW7Xa0ru49tD916q687XEwdBdLCBbtdq2/rj20P3XqrrztcTB0F0sIDwvcD48cD4gICAgLi4uIFvX7rrz0ru49tD916q687XEwdBdKSA8L3A+PHA+KSBBUyAmbHQ7zqrQ/deqse3WuLaotcSx8MP7Jmd0OyA8L3A+PHA+IDwvcD48cD4mbHQ7v8nRobXEIE9SREVSIEJZINfTvuQmZ3Q7OzwvcD48cD7OqsHLyrXP1tDQtcTQ/deqo6zUtLLp0a+78bXDtcS94bn706a1sb7fsbjI/cHQo6yyxcTcubvKtc/W0P3XqqGjtdoxwdDKx7K7vfjQ0ND916q1xMHQo6zK9NPaserWvsHQo7u12jLB0MrHyvTQ1MHQo6zSsrPGzqrNuMrTwdCjrMbk1tC1xNa1u+Gxu9D916rB0MP7o7u12jPB0MrHyvTQ1Na1wdCjrNXi0KnWtb2r1/fOqtDCwdC1xNa1oaPKudPDz8LD5rXE0+++5LS0vajSu7j2yr7A/bHtT3JkZXJzo6zE2sjdyOex7TktN8v5yr6hozwvcD48cD5DUkVBVEUgVEFCTEUgT3JkZXJzPC9wPjxwPig8L3A+PHA+ICAgUHJvZHVjdElEIGludCBOT1QgTlVMTCw8L3A+PHA+ICAgT3JkZXJEYXRlIGRhdGV0aW1lIE5PVCBOVUxMLDwvcD48cD4gICBTaGlwVG8gY2hhcigyMCkgTk9UIE5VTEwsPC9wPjxwPiAgIFN1YlRvdGFsIG1vbmV5IE5PVCBOVUxMPC9wPjxwPik7PC9wPjxwPklOU0VSVCBJTlRPIE9yZGVycyA8L3A+PHA+VkFMVUVTICgxLENBU1Qo"20090102' AS datetime), 'Shanghai', 100.00),

(1, CAST('20090105' AS datetime), 'Shanghai',100.00),

(1, CAST('20090123' AS datetime),'Jinan', 100.00),

(2, CAST('20090125' AS datetime),'Shanghai', 100.00),

(1, CAST('20090205' AS datetime),'Jinan', 100.00),

(3, CAST('20090213' AS datetime),'Shanghai', 100.00),

(3, CAST('20090219' AS datetime),'Shanghai', 100.00),

(4, CAST('20090309' AS datetime),'Beijing', 100.00),

(1, CAST('20090311' AS datetime),'Dalian', 100.00),

(2, CAST('20090324' AS datetime),'Shanghai', 100.00),

(3, CAST('20090326' AS datetime),'Wuhan', 100.00);

表9-7 Orders表的内容

ProductID

OrderDate

ShipTo

SubTotal

1

2009-01-02 00:00:00.000

Shanghai

100.00

1

2009-01-05 00:00:00.000

Shanghai

100.00

1

2009-01-23 00:00:00.000

Jinan

100.00

2

2009-01-25 00:00:00.000

Shanghai

100.00

1

2009-02-05 00:00:00.000

Jinan

100.00

3

2009-02-13 00:00:00.000

Shanghai

100.00

3

2009-02-19 00:00:00.000

Shanghai

100.00

4

2009-03-09 00:00:00.000

Beijing

100.00

1

2009-03-11 00:00:00.000

Dalian

100.00

2

2009-03-24 00:00:00.000

Shanghai

100.00

3

2009-03-26 00:00:00.000

Wuhan

100.00

Orders表中包含了3个月的产品销售数据,现在假设要获得像图9-4所示的销售表,则对源表的查询首先需要获得上面讲的三列,参考下面的语句:

SELECT ProductID,

MONTH(OrderDate) AS OrderMonth,

SubTotal

FROM Orders;

查询结果如表9-8所示。其中ProductID为标志列,OrderMonth为属性列,其中的月份要转变为列的名称,SubTotal为属性值列,这些值将成为新列的值。

表9-8 获取到的三列内容

ProductID

OrderMonth

SubTotal

1

1

100.00

1

1

100.00

1

1

100.00

2

1

100.00

1

2

100.00

3

2

100.00

3

2

100.00

4

3

100.00

1

3

100.00

2

3

100.00

3

3

100.00

完整的旋转查询语句如下。查询结果如表9-9所示。

SELECT ProductID,

[1]AS Jan,

[2]AS Feb,

[3]AS Mar

FROM (SELECT ProductID, MONTH(OrderDate) ASOrderMonth, SubTotal

FROMOrders) AS O1

PIVOT

(

SUM(SubTotal)

FOROrderMonth IN ([1], [2], [3])

) AS Pvt

ORDER BY ProductID;

表9-9 旋转后输出的内容

ProductID

Jan

Feb

Mar

1

300.00

100.00

100.00

2

100.00

NULL

100.00

3

NULL

200.00

100.00

4

NULL

NULL

100.00

上面的查询语句将按下面的步骤来获取表9-9所示的结果集:

PIVOT首先按属性值列之外的列(ProductID和OrderMonth)对输入表Sales.Orders进行分组汇总,类似执行下面的语句,得到一个如表9-10所示的中间结果集。

SELECT ProductID,

OrderMonth,

SUM(SubTotal) AS SubTotal

FROM (SELECT ProductID,MONTH(OrderDate) AS OrderMonth, SubTotal

FROM Orders) AS O1

GROUP BY ProductID,OrderMonth;

表9-10 Orders经分组汇总后的结果

ProductID

OrderMonth

SubTotal

1

1

300.00

1

2

100.00

1

3

100.00

2

1

100.00

2

3

100.00

3

2

200.00

3

3

100.00

4

3

100.00

PIVOT根据FOR OrderMonth IN指定的值1、2、3,首先在结果集中建立名为1、2、3的列,然后从表9-10所示的中间结果中取出SubTotal列中取出相符合的值,分别放置到1、2、3列中。此时得到的结果集的别名为pvt(见语句中AS pvt的指定)。结果集的内容如表9-11所示。

表9-11 使用FOR OrderMonth IN ([1], [2], [3])后得到的结果集

ProductID

1

2

3

1

300.00

100.00

100.00

2

100.00

NULL

100.00

3

NULL

200.00

100.00

4

NULL

NULL

100.00

最后根据SELECT ProductID, [1] AS Jan,[2] AS Feb, [3] AS Mar FROM的指定,从别名pvt结果集中检索数据,并分别将名为1、2、3的列在最终结果集中重新命名为Jan、Feb、Mar,得到表9-9所示的结果集。这里

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C#同步SQLServer数据库中的数据--.. 下一篇SQL语句行列转换两种方法case .....

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Sphinx : 高性能SQL (2025-12-24 10:18:11)
·Pandas 性能优化 - (2025-12-24 10:18:08)
·MySQL 索引 - 菜鸟教 (2025-12-24 10:18:06)
·Shell 基本运算符 - (2025-12-24 09:52:56)
·Shell 函数 | 菜鸟教 (2025-12-24 09:52:54)