Mysql5 实现交叉表查询

article/2025/5/14 12:08:55

交叉表、行列转换和交叉查询经典
一、什么是交叉表

“交叉表”对象是一个网格,用来根据指定的条件返回值。数据显示在压缩行和列中。这种格式易于比较数据并辨别其趋势。它由三个元素组成:
    行
    列
    摘要字段
    “交叉表”中的行沿水平方向延伸(从一侧到另一侧)。在上面的示例中,“手套”(Gloves) 是一行。
    “交叉表”中的列沿垂直方向延伸(上下)。在上面的示例中,“美国”(USA) 是一列。
    汇总字段位于行和列的交叉处。每个交叉处的值代表对既满足行条件又满足列条件的记录的汇总(求和、计数等)。在上面的示例中,“手套”和“美国”交叉处的值是四,这是在美国销售的手套的数量。

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

    每行的结尾是该行的总计。在上面的例子中,该总计代表一个产品在所有国家/地区的销售量。“手套”行结尾处的值是 8,这就是手套在所有国家/地区销售的总数。

    注意:    总计列可以出现在每一行的开头。
    每列的底部是该列的总计。在上面的例子中,该总计代表所有产品在一个国家/地区的销售量。“美国”一列底部的值是四,这是所有产品(手套、腰带和鞋子)在美国销售的总数。

    注意:    总计列可以出现在每一行的顶部。
    “总计”(Total) 列(产品总计)和“总计”(Total) 行(国家/地区总计)的交叉处是总计。在上面的例子中,“总计”列和“总计”行交叉处的值是 12,这是所有产品在所有国家/地区销售的总数。

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

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

Java代码   收藏代码
  1. # Host: localhost    Database: test  
  2. # ------------------------------------------------------  
  3. # Server version 5.0.45-community-nt-log  
  4.   
  5. #  
  6. # Table structure for table sale  
  7. #  
  8.   
  9. DROP TABLE IF EXISTS `sale`;  
  10. CREATE TABLE `sale` (  
  11. `id` int(10) unsigned NOT NULL auto_increment,  
  12. `year` int(11) NOT NULL,  
  13. `quarter` int(11) NOT NULL,  
  14. `amount` decimal(15,2) NOT NULL,  
  15. PRIMARY KEY (`id`)  
  16. ) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;  
  17.   
  18. #  
  19. # Dumping data for table sale  
  20. #  
  21.   
  22. /*!40101 SET NAMES latin1 */;  
  23.   
  24. INSERT INTO `sale` VALUES (1,2004,1,2328);  
  25. INSERT INTO `sale` VALUES (2,2004,2,3822);  
  26. INSERT INTO `sale` VALUES (3,2004,3,7071);  
  27. INSERT INTO `sale` VALUES (4,2004,4,8931);  
  28. INSERT INTO `sale` VALUES (5,2005,1,2633);  
  29. INSERT INTO `sale` VALUES (6,2005,2,3910);  
  30. INSERT INTO `sale` VALUES (7,2005,3,237193);  
  31. INSERT INTO `sale` VALUES (8,2005,4,567444);  
  32. INSERT INTO `sale` VALUES (9,2006,1,12313);  

插入数据后结果为:
id    year    quarter    amount
1    2004    1    2328.00
2    2004    2    3822.00
3    2004    3    7071.00
4    2004    4    8931.00
5    2005    1    2633.00
6    2005    2    3910.00
7    2005    3    237193.00
8    2005    4    567444.00
9    2006    1    12313.00

交叉表查询语句:
select a.year, 1d, 2d, 3d, 4d from
(select distinct year from sale) a left join
(select year, amount 1d from sale where quarter=1 group by year) a1d on a.year = a1d.year
left join (select year, amount 2d from sale where quarter=2 group by year) a2d on a2d.year=a.year
left join (select year, amount 3d from sale where quarter=3 group by year) a3d on a3d.year=a.year
left join (select year, amount 4d from sale where quarter=4 group by year) a4d on a4d.year=a.year
该语句查询某年的四个季度的amount,以行显示,显示结果:

year    1d    2d    3d    4d
2004    2328.00    3822.00    7071.00    8931.00
2005    2633.00    3910.00    237193.00    567444.00
2006    12313.00    NULL    NULL    NULL

实现定长列的查询(即quarter的最大取值为4,定长为4列).


http://chatgpt.dhexx.cn/article/yrAgn3vi.shtml

相关文章

access交叉表

一、交叉表查询每门课的成绩 交叉表&#xff1a;左边是行标题&#xff0c;上面是列标题&#xff0c;交叉的是值。更改字段名:更改字段名用双引号 二、查询每个年级的每门课的成绩 [表名]![字段名] 三、生成表 生成表&#xff1a;在一张表上生成一张新表原来只有三张表 点击运行…

access如何查询两张表的内容_Access使用技术2:使用交叉表查询向导进行每日汇总...

个人主页:http://office-access.cn公众号:DataMapHuanyu Access使用技术2:使用交叉表查询向导进行每日汇总 Access交叉表查询可以合并每日的量,日汇总功能对于大量数据统计是很有帮助的,Excel很难胜任。 1.技术要求 将不同的表用Union Select合并到一张表中,不能用两张表…

【Access数据库】关于带参数的交叉表查询

查了一圈&#xff0c;网上关于带参数的交叉表查询的介绍很少。 1.用SQL语句写带参数的交叉表查询的话&#xff0c;不能用having语句设置条件&#xff0c;必须用where。 2.where语句里不能像普通参数查询一样写模糊查询&#xff0c;必须是精确的。 3.即使用了where&#xff0c;也…

在MySQL中实现交叉表查询1(静态交叉表)

在MySQL中实现交叉表查询1&#xff08;静态交叉表&#xff09; 一、什么是交叉表 交叉表查询是将来源于某个表中的字段进行分组&#xff0c;一组列在交叉表左侧&#xff0c;一组列在交叉表上部&#xff0c;并在交叉表行与列交叉处显示表中某个字段的各种计算值。比如&#xf…

5.7.1 使用向导创建交叉表查询

示例ACCESS数据库下载链接&#xff1a; https://download.csdn.net/download/ngbshzhn/20979935 使用交叉表查询计算和重构数据&#xff0c;可以简化数据分析&#xff0c;交叉表查询计算数据的总和、平均值、计数或其他类型的总计值&#xff0c;并将它们分组。一组列在数…

5.7.2 使用设计视图创建交叉表查询

交叉表查询由三部分组成&#xff0c;行标题字段、列标题字段和值字段。按照Access的规定&#xff0c;列标题字段和值字段只能各有一个&#xff0c;行标题字段最多可以有3个。 (1)打开“罗斯文”数据库&#xff0c;在“创建”选项卡上的“查询”组中&#xff0c;单击“查询设…

计算机研究生学习路线

一、研究方向 研究方向来源&#xff1a;导师指定、咨询师兄师姐继续沿着他们的方向做深入研究、自己选方向。本节主要介绍自己如何选方向。 1.1paperswithcode 首先&#xff0c;进入The latest in Machine Learning | Papers With Code&#xff0c;我们可以看到主菜单栏&…

本人以及硕士期间研究介绍

读者们大家好 &#xff5e; 这篇博客是本人的第一篇博文&#xff0c;我将对自己的研究内容做一下简要的梳理&#xff0c;也欢迎感兴趣的小伙伴和我一起讨论。 &#xff5e; 我是一名工科硕士&#xff0c;本科就读于北京理工大学宇航学院&#xff0c;硕士期间申请硕博连读继续…

计算机学硕研究计划,博士研究生学习计划和研究计划

博士研究生学习计划和研究计划 时间是箭,去来迅疾,我们又将有新的学习内容,迎来新的挑战,是时候写学习计划了哦。好的学习计划都具备一些什么特点呢?以下是小编收集整理的博士研究生学习计划和研究计划,仅供参考,希望能够帮助到大家。 为了给博士学习生活开好头,不断学…

中职生职业生涯规划书2000字学计算机,计算机专业中职生职业生涯规划书

计算机专业中职生职业生涯规划书 下面是小编为中职生计算机专业整理的职业生涯规划书范文,供参考。 一、前言 九年义务教育,我们在儿童的懵懂、自由的嬉戏和父母的纵容中,快乐的度过;三年的高中生活,我们在学生们逐渐激烈的竞争、老师日益严肃的面孔和漫天飞舞的试卷中,艰…

python职业规划书_大学生职业规划书

职业生涯规划&#xff08;简称生涯规划&#xff09;&#xff0c;又叫职业生涯设计&#xff0c;是将个人与组织相结合&#xff0c;在对一个人职业生涯的主客观条件进行测定、分析、总结的基础上&#xff0c;对自己的兴趣、爱好、能力、特点进行综合分析与权衡&#xff0c;结合时…

回忆我的过去一年2020年考研以及研究生规划

目录 一、启发二、回忆考研录&#xff08;多图警告&#xff09;&#xff08;一&#xff09;大三寒假入门考研&#xff08;二&#xff09;大三下学期进入学习状态&#xff08;三&#xff09;大三暑假强化巩固知识&#xff08;四&#xff09;大四上学期冲刺考试&#xff08;五&am…

计算机专业读研期间的规划,【图片】2020考研,老学长教你如何规划!【计算机考研吧】_百度贴吧...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 二、关键一步——院校选择 我把各位同学的院校选择阶段分为以上几个阶段&#xff0c;因为考研这一年中&#xff0c;很多人的目标院校并不是固定不变的&#xff0c;而是随着不同阶段而改变的。学长我在大三下学期这一时间段内也多次…

源代码分析

/**/ // // 制作一个定时器&#xff0c;2位显示秒&#xff0c;2位显示分&#xff0c;用4个调节按钮调节 // 四个调节按钮为key0, key1, key2, key3分别为P3.2, P3.3, P3.4, P3.5 // 数码管用P0显示a,b,c,d,e,f,g&#xff0c;分别对应P0.0, P0.1, P0.2, P0.3, P0.4, P0.5, P0.6,…

IntelliJ IDEA 智能代码分析

IntelliJ IDEA 智能代码分析 # IntelliJ IDEA 会分析你的代码,在项目中查找文件和语言之间的关联。并使用这些信息,向你提供深度的代码帮助,快速导航,以及错误分析和重构。 1. IDEA的智能完成功能 // 按Ctrl+Shift+Space可以触发 // 通过Ctrl+Shift+Space快捷键组合,I…

Understand: 静态代码分析神器

一直以来&#xff0c;我以为Source Insight的代码分析已经是业界最强、最专业。今天试用了一下Scitools的Understand&#xff0c;导入代码后直接可以生成图形化分析结果&#xff0c;包括模块间调用&#xff0c;函数调用流程等&#xff0c;确实比较震撼。 文章目录 1. 设置2. 导…

RTMPdump 源代码分析 1: main()函数

RTMPdump(libRTMP) 源代码分析系列文章&#xff1a; RTMPdump 源代码分析 1&#xff1a; main()函数 RTMPDump (libRTMP) 源代码分析2&#xff1a;解析RTMP地址——RTMP_ParseURL() RTMPdump (libRTMP) 源代码分析3&#xff1a; AMF编码 RTMPdump (libRTMP) 源代码分析4&am…

JM代码分析(一)

JM代码分析&#xff08;一&#xff09; 入门视频采集与处理&#xff08;学会分析YUV数据&#xff09;核心编码函数研究码流控制RC去块滤波核心全局变量运动矢量的写码流从码流中提取NALU结构体00000(IDR)buf2img_basic宏块模式编码端写码流编码器&#xff1a;解码器&#xff1a…

代码分析:

爬虫组件分析 目录概述需求&#xff1a; 设计思路实现思路分析1.URL管理 DataTable 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,chall…

推荐一款源代码统计分析、开发工作量估算、测试缺陷预测的开发工具 —— 代码统计分析工具(SourceCounter)

目录 一、软件简介 二、主要功能 三、更新日志 四、关键字 一、软件简介 代码统计分析工具 4.0&#xff0c;支持 30多种代码格式。能够统计包括&#xff1a;代码行数、注释、空行、文件大小等数据。另外&#xff0c;还支持对软件开发项目的各个开发阶段的工数、成本、质量…