一、什么是交叉表
“交叉表”对象是一个网格,用来根据指定的条件返回值。数据显示在压缩行和列中。这种格式易于比较数据并辨别其趋势。它由三个元素组成:
- 行
- 列
- 摘要字段
- “交叉表”中的行沿水平方向延伸(从一侧到另一侧)。在上面的示例中,“手套”(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
相关推荐
交叉表行列实现动态转换
使用交叉表查询,显示源于表中某个字段的汇总值,并将它们分组,其中一组列在数据表的左侧,另一组列在数据表的上部。行和列的交叉处可以对数据进行多种汇总计算,如:求和、平均值、记数、最大值、最小值等。使用...
动态交叉表查询允许开发者根据需求自定义列和行,提供灵活的数据透视功能。本文将深入探讨C#中实现动态交叉表查询的相关知识点,并通过实例加以说明。 首先,理解什么是交叉表(Cross Tabulation)是关键。交叉表,...
实现动态交叉表的关键在于动态构建SQL查询语句,根据不同的数据维度和度量进行行列转换。下面介绍实现动态交叉表时可能涉及的几个关键知识点: 1. **动态SQL构建**:动态SQL是利用字符串构建SQL语句的技术。在存储...
在 Oracle 数据库中,我们可以使用行列转换和交叉查询来生成交叉表。例如,我们可以使用以下 SQL 语句来生成交叉表: select name,sum(case when a.subject='语文' then result else null end) as "语文", sum...
列联表(Cross Tabulation)和交叉表(Pivot Table)是这种转换的两种术语,它们用于将行数据转换为列数据,或者反之。在描述的场景中,我们需要在列不确定的情况下进行动态的行列转换。 首先,我们来看第一种方法...
- **频数统计**:交叉表主要进行数据的频数统计和汇总,通过行和列的索引对数据进行分组,并统计每个分组内的观测值数量,然后将这些频数填充到交叉表的对应位置。 - **数据聚合与行列分组**:数据聚合涉及将原始...
### 不定长的SELECT交叉表查询,且不用游标:SQL行列转换技术解析 #### 一、背景介绍 在数据库管理中,数据的组织形式多种多样,有时我们需要将原本存储为行的数据转换成列的形式展示,反之亦然。这种转换在实际...
这在生成交叉表、汇总数据等方面非常有用。具体语法如下: ```sql FROM table_source PIVOT (aggregate_function(value_column) FOR pivot_column IN (column_list)) AS table_alias ``` **参数解释**: - `table...
这通常用于创建交叉表或透视表,便于比较不同类别的数据。 2. **Unpivot操作(行转列)** 相反,"Unpivot"是将行转换为列的操作。假设你有一个表格,每行记录了一个产品的年度销售额。Unpivot操作可以将这些销售额...
交叉表是数据分析中的一种常见工具,它能够帮助我们以行列形式展示多维度数据,方便统计和比较。 首先,让我们深入理解C#与数据库的交互。在C#中,我们通常使用ADO.NET框架进行数据库操作。ADO.NET提供了一套完整的...
最后,对于列数不固定的情况,即所谓的交叉表行列转置,这是相对复杂的情况,通常需要编写PL/SQL过程。以一个电话统计表为例,包含类别的字段class1,日期字段calldate和呼叫次数字段callcount。我们需要将不同类别...
这种转换有助于数据分析和报表制作,因为它可以更直观地显示数据。在SQL中实现行转列可以通过多种方法,包括使用`CASE`语句、动态SQL、`PIVOT`操作符等。 ### 示例分析 #### 数据源 首先,我们来看看原始数据: `...
这个方法接收一个DataTable作为参数,将其转换成交叉表,即将原本的“姓名”作为行标识,原来的“科目”转换为列名,对应的“分数”作为新表格的值。如果某个学生在某一科目上没有分数,则该单元格的值设为"0"。 `...
例如,如果`grades`表还有一列`subject`,我们可以创建一个虚拟的交叉表: ```sql SELECT g1.student_id, g2.subject, g1.grade FROM grades g1 JOIN grades g2 ON g1.student_id = g2.student_id WHERE g1....
在IT领域,尤其是在数据分析和报表生成的过程中,交叉表(Pivot Table)是一种非常有用的工具,它可以帮助我们将数据按照特定的方式重新组织,以便更好地理解和分析。本文将深入探讨如何使用PHP来实现一个简单的数组...