交叉表、行列转换和交叉查询经典

一、什么是交叉表

“交叉表”对象是一个网格,用来根据指定的条件返回值。数据显示在压缩行和列中。这种格式易于比较数据并辨别其趋势。它由三个元素组成:

“交叉表”还可以包括若干总计:

二、行列转换和交叉查询:

1: 列转为行:
eg1:

假设有张学生成绩表(CJ)如下
name      subject         result
张三         语文             80
张三         数学             90
张三         物理             85
李四         语文             85
李四         数学             92
李四         物理             82

相关sql语句:

Create table CJ(name char(10),subject char(10),result int);

insert into CJ(name,subject,result) values('张三','语文',99);
insert into CJ(name,subject,result) values('张三','数学',86);
insert into CJ(name,subject,result) values('张三','英语',75);
insert into CJ(name,subject,result) values('李四','语文',78);
insert into CJ(name,subject,result) values('李四','数学',85);
insert into CJ(name,subject,result) values('李四','英语',78)
select * from CJ

想变成如下的交叉表    
姓名        语文        数学        物理
张三         99          90           85
李四         85          92           82

我们首先来看一下如何建立静态的交叉表,也就是说列数固定的交叉表,这种情况其实只要一句简单的Select查询就可以搞定:

select name,sum(case when a.subject='语文' then result else null end) as "语文",
                        sum(case when a.subject='数学' then result else null end) as "数学",
                        sum(case when a.subject='英语' then result else null end) as "英语"
           from CJ a
           group by name;

当要增加“总计”列:"合计总分"时,如下表所示:

姓名        合计总分 语文        数学        物理
张三          260             99          90          85
李四          241             85          92          82

只需增加sum(a.result) as "合计总分",sql如下:

select name,sum(a.result) as "合计总分",
                        sum(case when a.subject='语文' then result else null end) as "语文",
                        sum(case when a.subject='数学' then result else null end) as "数学",
                        sum(case when a.subject='英语' then result else null end) as "英语"
           from CJ a
           group by name;

其中利用了CASE语句判断,如果是相应的列,则取需要统计的cj数值,否则取NULL,然后再合计。
其中有两个常见问题说明一下:
a、用NULL而不用0是有道理的,假如用0,虽然求和函数SUM可以取到正确的数,但类似COUNT函数(取记录个数),结果就不对了,因为Null不算一条记录,而0要算,同理空字串("")也是这样,总之在这里应该用NULL,这样任何函数都没问题。

b、假如在视图的设计界面保存以上的查询,则会报错“没有输出列”,从而无法保存,其实只要在查询前面加上一段:Create View ViewName AS ...,ViewName是你准备给查询起的名称,...就是我们的查询,然后运行一下,就可以生成视图了,对于其他一些设计器不支持的语法,也可以这样保存。

以上查询作用也很大,对于很多情况,比如产品销售表中按照季度统计、按照月份统计等列头内容固定的情况,这样就行了,但往往大多数情况下列头内容是不固定的,象City,用户随时可能删除、添加一些城市,这种情况就是我们所说的动态交叉表,在SQLServer中我们可以用存储过程来解决。下面我们补充一些知识:

相关子查询

相关子查询和普通子查询区别在于:相关子查询引用了外部查询的列。这种引用外部查询的能力意味着相关子查询不能自己独立运行,其中对于外部查询引用会使会使其无法正常执行。因此相关子查询的执行顺序如下:
1.首先执行一遍外部查询
2.对于外部查询的每一行分别执行一遍子查询,而且每次执行子查询时候都会引用外部的当前行的值。使用子查询的结果来确定外部查询的结果集。
举个例子;
SELECT t1.type
FROM titles t1
GROUP BY t1.type
HAVING MAX(t1.advance) >=ALL
        (SELECT 2 * AVG(t2.advance)
        FROM titles t2
        WHERE t1.type = t2.type)
这个结果返回最高预付款超过给定组中平均预付款两倍的书籍类型。
再举个例子:
要求返回每一个编号的最大值(列出id,name,score)
ID Name(编号) Score(分数)
1          a                   88
2          b                   76
3          c                   66
4          c                   90
5          b                   77
6          a                   56
7          b                   77
8          c                   67
9          a                   44

select * from t a where score=
(select Max(Score) from t b       where a.name=b.name)
再给一个排位的sql语句
SELECT (
SELECT count(*) 1 as dd
FROM [Test ] as a where a.[F2]<b.[F2] ) AS ord,b.[F1], b.[F2]
FROM [Test ] as b
order by b.[F2];
好了关于sql的相关子查询先讲到这里。

SQLServer中局部变量赋值方法

有两种:
一种: set @变量名 = 值
二种: select @变量名 = 值

第二种可以从某个表中得到数据再赋值给变量
例: 从用户信息表中查询中cid为 20 的用户姓名将他赋值给变量 name
declare @name varchar(10) --用户名
select @name=userName from userInfo where cid = 20
print 'cid为20的用户姓名:' + @name

递归的select变量

递归的select变量是指使用select语句和子查询将一个变量与其自身拼接起来。语法形式如下:select @variable = @variable + table.column from table---见《sql server2000宝典》:P354,这是一种很优美的查询方法.从而将基础表中垂直的列数据改为水平方向的数据。这样就可以替代游标。动态的交叉表这样就代替了传统的游标。

SQL语句解决方法:

写法一:

declare @sql varchar(4000)
set @sql = 'select name'
select @sql = @sql + ',sum(case subject when '''+subject+''' then result end) as '+subject
             from (select distinct subject from CJ) as a
select @sql = @sql+' from CJ group by name'
exec(@sql)

写法二:

declare @sql varchar(4000)
set @sql = 'select name'
select @sql = @sql + ',sum(case subject when '''+subject+''' then result end) as '+subject
           +' from CJ group by subject
select @sql = @sql+' from CJ group by name'
exec(@sql)

具体不同的多种写法参见本文相关链接文章中的其他例子

在Access中还提供了TransForm来实现行列转换
TRANSFORM count(Result) AS number
SELECT 姓名
FROM 学生成绩表
GROUP BY 姓名
PIVOT Subject;

TransForm 用法如下:
=========================================================
TRANSFORM aggfunction
selectstatement
PIVOT pivotfield [IN (value1[, value2[, ...]])]

TRANSFORM 语句可分为以下几个部分:

部分                 描述
aggfunction 在选定数据上运作的 SQL 合计函数。
selectstatement       SELECT 语句。
pivotfield 在查询的结果集中创建列标题时用的字段或表达式。
value1, value2 用来创建列标题的固定值。

说明
使用交叉表查询来摘要数据时,从指定的字段或表达式中选定值作为列标题,
这样,可以用比选定查询更紧凑的格式来观察数据。
TRANSFORM 是可选的,但在使用它时,要作为       SQL 字符串中的第一个语句。
它出现在 SELECT 语句(指定作为行标题的字段的)之前,还出现在 GROUP BY 子句
(指定行分组的)之前。可以有选择地包含其它子句,例如 WHERE 子句,它指定附
加的选择或排序条件。也可以将子查询当作谓词,特别是在叉表查询的 WHERE 子句中。

pivotfield 返回的值被用作查询结果集中的列标题。
例如,在交叉表查询中,将根据销售图表按销售月份创建 12 个列。
可以限制 pivotfield 用列在可选的 IN 子句中的固定值(value1, value2)来创建标题。
也可以用没有数据存在的固定值来创建附加的列。

2. 列行转换
暂时保留

3. 行列转换--加合并
有表A,
id pid
1        1
1        2
1        3
2        1
2        2
3        1

如何化成表B:
id      pid
1       1,2,3
2       1,2
3       1

创建一个合并的函数
create function fmerg(@id int)
returns varchar(8000)
as
begin
declare @str varchar(8000)
set @str=''
select @str=@str+','+cast(pid as varchar) from 表A where id=@id
set @str=right(@str,len(@str)-1)
return(@str)
End
go

--调用自定义函数得到结果
select distinct id,dbo.fmerg(id) from 表A

相关链接:

把列变成行的sql语句: http://blog.csdn.net/liaoxiaohua1981/archive/2006/05/30/763721.aspx
应用SQL交叉表实现行列转换: http://blog.csdn.net/sivee/archive/2007/05/06/1598039.aspx
oracle 行列转换: http://blog.csdn.net/gogogo520/archive/2005/10/10/498779.aspx
行列转换例子: http://blog.csdn.net/zsl5305256/archive/2006/12/05/1430422.aspx
动态SQL的使用例子, 行列转换: http://blog.csdn.net/hertcloud/archive/2007/04/05/1552626.aspx
SqlServer如何生成动态交叉表查询: http://dev.csdn.net/article/12/12618.shtm
SQL语句精典收藏http://hi.baidu.com/suofang/blog/item/35de9d23af3e5945ad34de8a.html

交叉表、行列转换和交叉查询经典相关推荐

  1. SQL的交叉表、行列转换和交叉查询经典

    提要:这个问题是我也在笔试的时候出现的问题,当初看到题目,想到很多方法,当感觉脚本太过复杂,笔试完毕,在网上查询之后,整理了一下,写在这里与大家一起讨论学习. 1.题目: 张三和李四的成绩表(CJ)如 ...

  2. 普通行列转换(交叉表,横表变列表)

    SQL code /* 标题:普通行列转换(version 2.0) 作者:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开) 时间:2008-03-09 地点:广东深圳 说明:普通行列转换(versio ...

  3. java薪资年龄交叉表_巧用参数实现交叉表行列互换

    对于普通的没有olap分析功能的快逸报表而言,一旦发布到web页面后,其样式就被固定了,如果想把报表换种形式展现通常的做法是重新设计一张报表模板来实现,难道快逸报表就没有一种特殊的方法可以解决这样的需 ...

  4. [数据库] SQL查询语句表行列转换及一行数据转换成两列

    本文主要讲述了SQL查询语句表之间的行列转换,同时也包括如何将一行数据转换成两列数据的方法.子查询的应用.decode函数的用法.希望文章对你有所帮助~ 1.创建数据库表及插入数据 2.子查询统计不同 ...

  5. crosstab交叉表_透视图和交叉表

    透视图和交叉表 在数据分析中,数据透视表是常见的工具之一,需要根据行或列对数据进行各个维度数据的汇总,在pandas中,提供了相关函数解决此类问题 透视图相关函数 pivot_table(data,i ...

  6. 数据透视表与mysql_通过sql做数据透视表,数据库表行列转换(pivot和Unpivot用法)(一)...

    在mssql中大家都知道可以使用pivot来统计数据,实现像excel的透视表功能 一.MSsqlserver中我们通常的用法 1.Sqlserver数据库测试 ---创建测试表 Create tab ...

  7. wps交叉表_spss如何做交叉表分析

    在spss中打开数据,然后依次打开:analyze--descriptive--crosstabs,打开交叉表对话框 2将性别放到行列表,将对读物的选择变量放到列,这样就构成了一个交叉表 3接下来我们 ...

  8. mysql unpivot_SQL(横表和纵表)行列转换,PIVOT与UNPIVOT的区别和使用方法举例,合并列的例子...

    使用过SQL Server 2000的人都知道,要想实现行列转换,必须综合利用聚合函数和动态SQL,具体实现起来需要一定的技巧,而在SQL Server 2005中,使用新引进的关键字PIVOT/UN ...

  9. SQL CASE When THEN END 行列转换,复杂查询

    使用 CASE CASE 函数是特殊的 Transact-SQL 表达式,它允许按列值显式可选值.数据中的更改是临时的,没有对数据进行永久更改.例如,CASE 函数可以在 state 列中有 CA 值 ...

最新文章

  1. OFDM同步算法之Park算法
  2. 死锁的4个必要条件和处理策略
  3. C++ Primer 5th笔记(chap 19 特殊工具与技术)malloc 函数与 free 函数
  4. Codeforces Beta Round #4 (Div. 2)【完结】
  5. java写龟兔赛跑_简单的实现java多线程——龟兔赛跑
  6. 细数非对称加密与对称加密的区别
  7. html图片展示不间隙,求助大神 如让图片展示在li标签里面,不要间隙 谢谢
  8. 关于操作 ASP.NET Web API的实例
  9. Python中requests上传大文件
  10. 如何让你的程序员不要厌倦工作?
  11. Spark History Server 没有生效
  12. Android显示图片崩溃的解决办法
  13. 如何卸载重装Adobe Acrobat
  14. Android底层网络防火墙,Android系统中实现网络防火墙的方法
  15. Carson带你学Android:手把手带你深入分析事件分发机制!
  16. 强化学习、行为心理学和成瘾机制
  17. InTra【异常检测:Reconstruction_based】
  18. C语言基础之统计数字
  19. 20180423-B · Australian Salaries by Gender · ggplot2 ggalt geom_dumbbell 棒棒糖图 哑铃图 · R 语言数据可视化 案例 源码
  20. table如何正确的隐藏一列

热门文章

  1. Java的字符串连接符(+)
  2. 张一鸣打造“抖音”等现象级产品的秘密:技术深度融合业务,引爆产品创新!
  3. SEO诊断,如何查询网站是否被百度降权
  4. 目的:python 解决输出乱码问题形如\u63a5\u53e3\u8c03\u7528\u6210\u529f
  5. 我告诉你一个 AtomicInteger 的惊天大秘密
  6. grbl源码解析——速度前瞻(1)
  7. 思科交换机使用TFTP工具备份配置和上传配置
  8. 线性关系r范围_一个简单线性回归和多项式回归在R中的实现示例
  9. 聊天机器人技术分析综述
  10. 怎样使用PS制作木刻效果图片?添加木刻特效原来这么简单!