说明:本实例是以 SQL Server 2005 为运行环境的。

准备工作:创建一个名为 DB 的数据库(CREATE DATABASE DB)。

一、T-SQL 行转列

1、创建如下表

CREATE  TABLE [Scores]

(

[ID] INT IDENTITY(1,1), --自增标识

[StuNo] INT,                         --学号

[Subject] NVARCHAR(30),     --科目

[Score] FLOAT                    --成绩

)

GO

INSERT INTO [Scores]

SELECT 100, '语文', 80 UNION

SELECT 100, '数学', 75 UNION

SELECT 100, '英语', 70 UNION

SELECT 100, '生物', 85 UNION

SELECT 101, '语文', 80 UNION

SELECT 101, '数学', 90 UNION

SELECT 101, '英语', 70 UNION

SELECT 101, '生物', 85

CREATE  TABLE [Student]

(

[ID] INT IDENTITY(100,1),            --自增标识,学号

[StuName] NVARCHAR(30),           --姓名

[Sex] NVARCHAR(30),                      --性别

[Age] CHAR(2)                          --年龄

)

GO

INSERT INTO [Student]

SELECT '张三', '男', 80 UNION

SELECT '李四', '女', 75

两表的数据如下图:

2、通过CASE…WHEN 语句和GROUP BY…聚合函数 来实现行转列

SELECT

StuNo AS '学号',

MAX(CASE Subject WHEN '语文' THEN Score ELSE 0 END) AS '语文',

MAX(CASE Subject WHEN '数学' THEN Score ELSE 0 END) AS '数学',

MAX(CASE Subject WHEN '英语' THEN Score ELSE 0 END) AS '英语',

MAX(CASE Subject WHEN '生物' THEN Score ELSE 0 END) AS '生物',

SUM(Score) AS '总分',

AVG(Score) AS '平均分'

FROM dbo.[Scores]

GROUP BY StuNo

ORDER BY StuNo ASC

结果如下图:

3、通过 JOIN…ON 实现两表联接,显示出学生姓名

SELECT

MAX(StuNo) AS '学号',

StuName AS '姓名',

MAX(CASE Subject WHEN '语文' THEN Score ELSE 0 END) AS '语文',

MAX(CASE Subject WHEN '数学' THEN Score ELSE 0 END) AS '数学',

MAX(CASE Subject WHEN '英语' THEN Score ELSE 0 END) AS '英语',

MAX(CASE Subject WHEN '生物' THEN Score ELSE 0 END) AS '生物',

SUM(Score) AS '总分',

AVG(Score) AS '平均分'

FROM dbo.[Scores] A join [Student] B on (A.StuNo=B.ID)

GROUP BY StuName

ORDER BY StuName ASC

结果如下图:

4、通过 PIVOT 实现行转列

SELECT

StuNo AS '学号',

StuName AS '姓名',

AVG(语文) AS '语文',

AVG(数学) AS '数学',

AVG(英语) AS '英语',

AVG(生物) AS '生物'

FROM [Scores]

PIVOT(

AVG(Score) FOR Subject IN

(语文,数学,英语,生物)

) AS NewScores

JOIN [Student] ON (NewScores.StuNo=Student.ID)

GROUP BY NewScores.StuNo,StuName

ORDER BY StuName ASC

结果如下图:

二、T-SQL列转行

1、创建数据表并插入 4 条数据

CREATE  TABLE [StudentScores]

(

[ID] INT IDENTITY(1,1),       --自增标识

[StuNo] INT,                              --学号

[Chinese] NVARCHAR(30),          --语文

[Mathematics] NVARCHAR(30),   --数学

[English] NVARCHAR(30),           --英语

[Biology] NVARCHAR(30)              --生物

)

GO

INSERT INTO [StudentScores]

SELECT 100, 80, 85, 75, 80 UNION

SELECT 101, 90, 80, 70, 75 UNION

SELECT 102, 95, 90, 80, 70 UNION

SELECT 103, 60, 70, 80, 85

数据如下图:

2、通过 UNION ALL…MAX 实现列转行

SELECT StuNo, 'Chinese' AS Subject,

MAX(Chinese) AS 'Score'

FROM [StudentScores]

GROUP BY [StuNo]

UNION ALL

SELECT StuNo, 'Mathematics' AS Subject,

MAX(Mathematics) AS 'Score'

FROM [StudentScores]

GROUP BY [StuNo]

UNION ALL

SELECT StuNo, 'English' AS Subject,

MAX(English) AS 'Score'

FROM [StudentScores]

GROUP BY [StuNo]

UNION ALL

SELECT StuNo, 'Biology' AS Subject,

MAX(Biology) AS 'Score'

FROM [StudentScores]

GROUP BY [StuNo]

结果如下图:

3、用 UNPIVOT 实现列转行

SELECT StuNo, Subject, Score

FROM [StudentScores]

UNPIVOT

(

Score FOR Subject IN

([Chinese], [Mathematics], [English], [Biology])

) AS NewStudentScores

EXEC sp_dbcmptlevel db_16, 90;

三、T-SQL 分页

1、创建数据库并插入 40000 条数据

CREATE  TABLE [Pagin]  (

[ID] INT IDENTITY(1,1), --自增标识

[Number] INT,                     --编号

[Type] NVARCHAR(30),           --类型

[Count] INT                          --数量

)

GO

declare @i int

set @i = 0

while(@i<10000)

begin

INSERT INTO [Pagin] SELECT 10000+@i, 'A类', 80+@i%5

INSERT INTO [Pagin] SELECT 10000+@i, 'B类', 60+@i%10

INSERT INTO [Pagin] SELECT 10000+@i, 'C类', 70+@i%8

INSERT INTO [Pagin] SELECT 10000+@i, 'D类', 90+@i%3

set @i = @i + 1

end

2、通过 TOP 实现分页

方案一:两次 TOP 实现,原型如下

SELECT * FROM

(

SELECT TOP 5 * FROM

(

SELECT TOP 25 * FROM [Pagin] WHERE ID>0 ORDER BY ID ASC

) AS TEMPTABLE1 ORDER BY ID DESC

) AS TEMPTABLE2 ORDER BY ID ASC

SELECT TOP 5 * FROM

(

SELECT TOP 25 * FROM [Pagin] WHERE ID>0 ORDER BY ID ASC

) AS TEMPTABLE1 ORDER BY ID DESC

说明:第一个 TOP 表示页面容量,第二个 TOP 表示页面容量*当前页码数。

弊病:     1、强制排序,否则不能分页,虽然目前基本上查询表都要排序。

2、排序字段不能有空值即null,否则分页结果不符实际情况。

3、多次order by 速度会快吗,有待我进一步大数据量测试。

方案二:两次 TOP 基于NOT IN 实现,原型如下

select top 5 * from [Pagin]

where ID not in (select top 25 ID from [Pagin] order by ID)

order by ID

说明:第一个 TOP 表示页面容量,第二个 TOP 表示页面容量*当前页码数。

弊病:     1、强制排序。

2、排序列必须是唯一列,否则分页情况不符实际。

3、使用not   in,速度慢。

方案三:两次 TOP 基于MAX 或 MIN 实现,原型如下

select top 5 * from [Pagin]

where ID > (select max(p.ID) from (select top 25 ID from [Pagin] order by id) as p)

order by ID

说明:第一个 TOP 表示页面容量,第二个 TOP 表示页面容量*当前页码数。

弊病:     1、强制排序。

2、排序列必须是唯一列,否则分页情况不符实际。

最后总结:在 sqlserver  分页中,第二第三种方案基本上是淘汰掉的,因为现在基本上什么表都是根据添加时间来排序,所以那两种方案没有用,真亏作者也敢发布出来,只有第一种方案还是稍微能用一下,但还是要复杂的拼sql 语句,不方便,要通用于所有表有点难度,象oracle 就很方便了,基于rownum ,传入一个sql 查询语句,这个查询语句爱怎么写就怎么写,反正保证它得到一个结果集就行,不像sqlserver又是要求唯一健又是要求必须排序,把一个结果集颠来倒去,不慢才怪呢。

方案一的简单存储过程如下:

CREATE PROCEDURE proc_page

@pageIndex INT = 0,                   --页索引

@pageSize INT = 10,                   --页大小

@recordCount INT = 0 OUTPUT,     --返回纪录总数

@pageCount INT = 0 OUTPUT        --返回页总数

AS

DECLARE @sql NVARCHAR(1300)           --主sql语句

--得到记录总数--

BEGIN

DECLARE @recordTotal INT

SET @sql = N'SELECT @recordTotal=COUNT(ID) FROM [Pagin] WHERE ID>0'

EXEC SP_EXECUTESQL @sql,N'@recordTotal INT OUTPUT',@recordTotal OUTPUT --@recordTotal = @recordCount OUTPUT

SET @recordCount = @recordTotal

END

--计算页总数--

IF(@recordCount%@pageSize=0)--如果记录总数除以页大小的余数为零

SET @pageCount = @recordCount/@pageSize

ELSE--如果记录总数除以页大小的余数不为零

SET @pageCount = @recordCount/@pageSize + 1

--根据页索引执行分页查询--

IF(@pageIndex<=1 OR @pageIndex>@pageCount)--如果是第一页,或者该页不存在,则默认也索引为1,即第一页

BEGIN

SET @pageIndex = 1

SET @sql = 'SELECT TOP '+STR(@pageSize)+' * FROM [Pagin] WHERE ID>0 ORDER BY ID ASC'

EXEC SP_EXECUTESQL @sql

END

ELSE--如果不是第一页,即其它页

BEGIN

SET @sql = 'SELECT * FROM (SELECT TOP '+STR(@pageSize)+' * FROM (SELECT TOP '+STR(@pageSize*@pageIndex)+' * FROM [Pagin] WHERE ID>0 ORDER BY ID ASC) AS TB1 ORDER BY ID DESC) AS TB2 ORDER BY ID ASC'

EXEC SP_EXECUTESQL @sql

END

PRINT @sql--打印SQL 语句

GO

--测试

DECLARE @recordCount INT,@pageCount INT

EXEC   proc_page 0,5,@recordCount OUTPUT,@pageCount OUTPUT

PRINT @recordCount

PRINT @pageCount

注意:该存储过程是扩展的,还可以改为万能分页存储过程,只需再加上一些参数,再改改就好了。

Sql 行转列、列转行及分页的更多相关文章

  1. SQL 行转列和列转行

    SQL 行转列和列转行 行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过 ...

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

    转载:http://www.cnblogs.com/newwind521/archive/2010/11/25/1887203.html sql 行专列 列转行 普通行列转换 /* 标题:普通行列转换 ...

  3. sql 行转列 PIVOT 列转行 UNPIVOT

    原文:sql 行转列 PIVOT 列转行 UNPIVOT 一: 现有表一(t_table1),想转为表二(t_table2)的格式. 表一: 年 公司 收入 2013 公司1 12 2013 公司2 ...

  4. SQL Server 行转列,列转行。多行转成一列

    一.多行转成一列(并以","隔开) 表名:A 表数据: 想要的查询结果: 查询语句: SELECT name , value = ( STUFF(( SELECT ',' + va ...

  5. SQL行转列,列转行

    SQL 行转列,列转行 行列转换在做报表分析时还是经常会遇到的,今天就说一下如何实现行列转换吧. 行列转换就是如下图所示两种展示形式的互相转换 行转列 假如我们有下表: SELECT * FROM s ...

  6. Sql server 中将数据行转列列转行(二)

    老规矩,先弄一波测试数据,数据填充代码没有什么意义,先折叠起来: /* 第一步:创建临时表结构 */ CREATE TABLE #Student --创建临时表 ( StuName ), --学生名称 ...

  7. SQL2005语句实现行转列,列转行

    在做报表时,经常需要将数据表中的行转列,或者列转行,如果不知道方法,你会觉得通过SQL语句来实现非常难.这里,我将使用pivot和unpivot来实现看似复杂的功能.这个功能在sql2005及以上版本 ...

  8. Ms sql行转列。汇总

    SQL行转列汇总 PIVOT 用于将列值旋转为列名(即行转列),在 SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT 的一般语法是:PIVOT(聚合函数(列) FOR 列 ...

  9. sql 行转列总结

    原文:sql 行转列总结 PIVOT UNPIVOT的用法 PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...

  10. Sql 行转换为列 以及列转换为行的心得

    这是 创建数据库的脚本文件 CREATE TABLE [dbo].[stu]( [学号] [nvarchar](255) NOT NULL, [姓名] [nvarchar](255) NULL, [性 ...

随机推荐

  1. 没有懂的leetcode

    Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in ...

  2. java中的数据库事务处理

    /*java使用事务处理,首先要求数据库支持事务,如使用MYSQL的事务功能,就要求mysql的表类型为Innodb,*/ /*InnoDB,是MySQL的数据库引擎之一 与传统的ISAM与MyISA ...

  3. PT与PX,em(%)区别

    字体大小的设置单位,常用的有2种:px.pt.这两个有什么区别呢?先搞清基本概念:px就是表示pixel,像素,是屏幕上显示数据的最基本的点:pt就是point,是印刷行业常用单位,等于1/72英寸. ...

  4. 【转】 iOS Provisioning Profile(Certificate)与Code Signing详解

    原文:http://blog.csdn.net/phunxm/article/details/42685597 引言 关于开发证书配置(Certificates & Identifiers & ...

  5. CoreLocation+MapKit系统定位(含坐标以及详细地址)

    iOS8 之后出现一些新的配置 [self.manager requestWhenInUseAuthorization]; 并且在info.plist文件中增加 NSLocationWhenInUse ...

  6. 【USACO 3.1.3】丑数

    [描述] 对于一给定的素数集合 S = {p1, p2, ..., pK}, 来考虑那些质因数全部属于S 的数的集合.这个集合包括,p1, p1p2, p1p1, 和 p1p2p3 (还有其它).这是 ...

  7. Python正则表达式+自创口诀

    重新学习了Python正则表达式,看了一些很好的学习博客,向大家推荐这个. 感谢作者@AstralWind 博客地址:http://www.cnblogs.com/huxi/archive/2010/ ...

  8. 面向对象设计模式之Facade外观模式(结构型)

    动机:有些系统组件的客户和组件中各种复杂的子系统有了过多的的耦合,随着外部客户程序  和个子系统的演化,这种过多的耦合面临很多变化的挑战:如何简化外部客户程序和系统的交互接口?  如何将外部客户程序的 ...

  9. Win7 64位 php-5.5.13+Apache 2.4.9+mysql-5.6.19 配置

    一 :准备阶段 1:php php-5.5.13下载链接:http://windows.php.net/downloads/releases/php-5.5.13-Win32-VC11-x64.zip ...

  10. 大脑皮层是如何工作的 《人工智能的未来》(<On intelligence>)读书笔记

    PS:今年寒假的读书笔记,挖下的坑已无力再填...不过有关智能和人工智能的书还是要继续读的~ 正文: 我觉得书名翻译不是很确切,全书讨论的核心应该更是在“真”智能:讨论对人脑智能的理解,可以怎样帮助我 ...