MSSQL_8 操作结果集
目录
- 合并结果集
- 查询结果集的差异行
- 查询结果集的相同行
- 优先级(INTERSECT > UNION = EXCEPT
- 公用表表达式(CTE)
- 汇总数据(CUBE, ROLLUP, GROUPING)
联接操作无论多么复杂,都被看作一条查询语句。
对结果集的操作则是对至少两条查询语句的结果再次整合。要求:两个结果集的列数相同,列的顺序相同,且相应列的数据类型也应当相同,或能隐式转换。
喻:联接操作是对两个表进行横向结合,结果集操作是对两个表纵向结合。
1.合并结果集
一个SQL语句可以出现任意数目的UNION运算符。
保留第1个SELECT语句的结果集的列名。
-- UNION 删除重复行
-- UNION ALL 保留重复行
selete_statement UNION [ALL] select_statement
IF DB_ID('tt') IS NOT NULLDROP DATABASE tt
GO
CREATE DATABASE tt
GO
IF OBJECT_ID('tt.dbo.T1') IS NOT NULLDROP TABLE T1
IF OBJECT_ID('tt.dbo.T2') IS NOT NULLDROP TABLE T2
GO
CREATE TABLE tt.dbo.T1
(A int, B char(5),C char(4)
)
CREATE TABLE tt.dbo.T2
(A char(4),B decimal(5, 4)
)
GO
INSERT INTO tt.dbo.T1
VALUES(1, 'ABC', 'JKL'), (2, 'DEF', 'MNO'), (3, 'GHI', 'PQR')
INSERT INTO tt.dbo.T2
VALUES('JKL', 1.000), ('DEF', 2.000), ('MNO', 5.000)
GOSELECT A, B FROM tt.dbo.T1
UNION
SELECT B, A FROM tt.dbo.T2
GO-- 在UNION运算符中
-- ORDER BY 作用于第1个结果集的列名
SELECT A, B FROM tt.dbo.T1
UNION
SELECT B, A FROM tt.dbo.T2
ORDER BY A
-- 在ORDER BY中
-- 其它逻辑处理需要要ORDER BY之前
SELECT A, B FROM tt.dbo.T1
WHERE B <> 'ABC'
UNION
SELECT B, A FROM tt.dbo.T2
WHERE A <> 'DEF'
ORDER BY A
GO-- 合并顺序
-- 一般中从左到右依次(上下),可使用圆括号'()'改变运算顺序
-- 加上括号后,先T2,T3,后T1
SELECT * FROM T1
UNION ALL
(SELECT * FROM T2
UNION
SELECT * FROM T3)
2.查询结果集的差异行
EXCEPT
运算符。
返回上表中,与下表的差异行,去重。从上到下(左右)运算,返回上侧表中含有,但下侧表中没有有结果集。
- 全部差异行
❶是否存在(NULL),❷左侧查询与右侧查询中重复行的次数
+NULL,不去重
注:“三值逻辑”。
-- ROW_NUMBER() 辅助列
IF DB_ID('tt') IS NOT NULLDROP DATABASE tt
GO
CREATE DATABASE tt
GOIF OBJECT_ID('tt.dbo.T1') IS NOT NULLDROP TABLE T1
IF OBJECT_ID('tt.dbo.T2') IS NOT NULLDROP TABLE T2
GO
CREATE TABLE tt.dbo.T1
(A int
)
CREATE TABLE tt.dbo.T2
(A int
)
GO
INSERT INTO tt.dbo.T1
VALUES(NULL), (NULL), (NULL), (1), (2), (3), (3), (4), (4), (4)
INSERT INTO tt.dbo.T2
VALUES(NULL), (2), (3), (3), (4)
GO
SELECT A FROM tt.dbo.T1
SELECT A FROM tt.dbo.T2
GO
-- 除NULL,去重
SELECT A FROM tt.dbo.T1
EXCEPT
SELECT A FROM tt.dbo.T2
GO
-- +NULL,不去重
SELECT A
FROM (SELECT ROW_NUMBER() OVER(PARTITION BY A ORDER BY A) rn, AFROM tt.dbo.T1EXCEPTSELECT ROW_NUMBER() OVER(PARTITION BY A ORDER BY A) rn, AFROM tt.dbo.T2) T
3.查询结果集的相同行
INTERSECT
运算符
返回左右表都存在的行,去重
SELECT A FROM tt.dbo.T1
INTERSECT
SELECT A FROM tt.dbo.T2
- 查询全部相同行
+NULL,不去重
-- 辅助行 ROW_NUMBER() OVER()SELECT A FROM tt.dbo.T1
SELECT A FROM tt.dbo.T2
GO
-- 去重
SELECT A FROM tt.dbo.T1
INTERSECT
SELECT A FROM tt.dbo.T2
GO
-- 不去重
SELECT A, ROW_NUMBER() OVER(PARTITION BY A ORDER BY A) rn
FROM tt.dbo.T1
INTERSECT
SELECT A, ROW_NUMBER() OVER(PARTITION BY A ORDER BY A) rn
FROM tt.dbo.T2
GO
4.优先级
INTERSECT > UNION = EXCEPT, 如果有圆括号,先执行圆括号()内的语句
5.公用表表达式(Common Table Expression, CTE)
临时(#)结果集
可调用自身,实现递归,可以同一查询中引用多次
5.1 语法
-- CTE表达式的名称 cte_name
-- 列列表 col_name [, ...n]
-- 创建临时结果集的查询语句 cte_query_definition
WITH cte_name [ ( col_name [, ...n] ) ]
AS
( cte_query_definition )
5.2 创建
CTE
后必须跟随引用部分或单条SELECT、INSERT、UPDATE或DELETE语句,CTE仅对该语句可见。
- CTE中不能再嵌套CTE
- cte_query_definition中不能使用
1.ORDER BY(当指定了TOP子名时,可以)
2.INTO
3.带查询提示的OPTION子句1
注:对于非计算列,列名称的定义可以完全省略。计算列必须在开头或查询定义部分指定别名。
5.2.1 单CTE
WITH cte_t1
AS
(SELECT A FROM tt.dbo.T1UNIONSELECT A FROM tt.dbo.T2
)
SELECT * FROM cte_t1
GO
CREATE TABLE tt.dbo.sale
(id int,name varchar(20),dat datetime
)
insert into tt.dbo.sale
values(1, 'H', '2019-10-10'), (2, 'S', '2019-10-22')
GO
select * from tt.dbo.sale
gowith cte_sal
as
(select * from tt.dbo.sale
)
select * from cte_sal
gowith cte_sal1 (dd, nn)
as
(select id, name from tt.dbo.sale
)
select * from cte_sal1
gowith cte_sal2(id, Y, C)
as
(select id, YEAR(dat) year_, COUNT(id) cntfrom tt.dbo.salegroup by id, YEAR(dat)
)
select * from cte_sal2
5.2.2 多CTE定义和CTE多次引用
WITH子句中可同时定义多个CTE
eg.1 多CTE定义
with cte_sal2 as
(select id, YEAR(dat) year_, COUNT(id) cntfrom tt.dbo.salegroup by id, YEAR(dat)
), -- 逗号分隔即可
cte_sal3 as
(select year_, COUNT(cnt) Cntfrom cte_sal2group by year_
)
select * from cte_sal3
eg.2 CTE多次引用
-- 派生表
use [Account Management]
go
SELECT Cur.Mon AS CurMon, Prv.Mon AS PrvMon, Cur.Spending AS CurSpending, Cur.Spending - Prv.Spending AS Diff
FROM (SELECT MONTH(日期) AS Mon, SUM(金额) AS SpendingFROM 消费GROUP BY MONTH(日期)) AS CurLEFT JOIN(SELECT MONTH(日期) AS Mon, SUM(金额) AS SpendingFROM 消费GROUP BY MONTH(日期)) AS PrvON Cur.Mon = Prv.Mon + 1
ORDER BY CurMon
GO-- 等价
-- CTE 多次引用
WITH cte_MonDiff AS
(SELECT MONTH(日期) AS Mon, SUM(金额) AS SpendingFROM 消费GROUP BY MONTH(日期)
)
SELECT Cur.Mon AS CurMon, Prv.Mon AS PrvMon, Cur.Spending AS CurSpending, Cur.Spending - Prv.Spending AS Diff
FROM cte_MonDiff CurLEFT JOIN cte_MonDiff PrvON Cur.Mon = Prv.Mon + 1
ORDER BY CurMon
GO
5.2.3 CTE间接嵌套
由于不能直接嵌套,但可以通过在视图、用户定义函数(UDF)中定义CTE的方式
(就是找个临时存储空间将数据存储起来,感觉间接嵌套实用意义不大,快消是CTE的优点,没必要补足)
-- 通过VIEW间接实现
--
use [Account Management]
go
CREATE VIEW v_Mon
AS
WITH cte_mon AS
(SELECT MONTH(日期) AS Mon, SUM(金额) AS SpendingFROM 消费GROUP BY MONTH(日期)
)
SELECT * FROM cte_mon
GO
WITH cte_MOM AS
(SELECT Cur.Mon AS CurMon, Prv.Mon AS PrvMon, Cur.Spending AS CurSpending, Cur.Spending - Prv.Spending AS DiffFROM v_Mon CurLEFT JOIN v_Mon PrvON Cur.Mon = Prv.Mon + 1
)
SELECT *
FROM cte_MOM
ORDER BY CurMon
GO
DROP VIEW v_Mon -- 删除演示数据-- 通过UDF
--
CREATE FUNCTION dbo.fn_query(@class varchar(20))RETURNS TABLE
AS
RETURN
WITH cte_m AS
(SELECT MONTH(日期) AS Mon, SUM(金额) AS SpendingFROM 消费WHERE 类别 = @classGROUP BY MONTH(日期)
)
SELECT * FROM cte_m
GO
select * from sysobjects where xtype not in ('S', 'IT', 'SQ', 'U', 'V', 'P', 'PK')
GO
WITH cteMonDiff AS
(SELECT Cur.Mon AS CurMon, Prv.Mon AS PrvMon, Cur.Spending AS CurSpending, Cur.Spending - Prv.Spending AS MonDiffFROM dbo.fn_query('总点击') AS CurLEFT JOIN dbo.fn_query('总点击') AS PrvON Cur.Mon = Prv.Mon + 1
)
SELECT *
FROM cteMonDiff
ORDER BY CurMon
GO
DROP FUNCTION dbo.fn_query
GO
5.2.4 递归CTE
重复执行初始CTE返回数据子集,直到获取完整结果集的公用表表达式。
递归查询,即当查询引用递归CTE。用于返回分层数据。
了解即可
USE master
GO
IF DB_ID('tt') IS NOT NULLDROP DATABASE tt
GO
CREATE DATABASE tt
GO
CREATE TABLE tt.dbo.Emp
(emp_id int,manager_id int,emp_name varchar(50),salary money
)
INSERT INTO tt.dbo.Emp
VALUES(1, NULL, 'A1', 10000.00), (2, 1, 'B1', 9000.00),(3, 1, 'B2', 9000.00), (4, 2, 'C1', 8000.00),(5, 2, 'C2', 8000.00), (6, 3, 'C3', 8000.00)
GO
SELECT * FROM tt.dbo.Emp
GO
WITH etc_DR AS
(-- 定位点成员 --必须,至少1个SELECT manager_id, emp_id, emp_name, 0 AS levelFROM tt.dbo.EmpWHERE manager_id IS NULLUNION ALL -- 必须,连接定位点成员与递归组成员-- 递归成员 -- 必须,只有1个SELECT e.manager_id, e.emp_id, e.emp_name, level + 1FROM tt.dbo.Emp AS eINNER JOIN etc_DR AS dON e.manager_id = d.emp_id
)
-- 执行CTE
SELECT * FROM etc_DR
-- WHERE level < 2
-- OPTION(MAXRECURSION 3) -- 默认100,限制递归调用次数
GO
6.汇总数据
当需要统计分析的列较多时,单纯使用GROUP BY会非常繁琐。且多次聚合计算不仅增加了往返查询的次数,同时增加了系统负担。
GROUP BY
增加了CUBE
和ROLLUP
参数。
- CUBE运算符
基于要分析的数据列建立结果集(多维数据集)
CREATE TABLE tt.dbo.voc
(item varchar(20),color varchar(20),quantity int
)
INSERT INTO tt.dbo.voc
VALUES('Chair', 'blue', 1), ('Chair', 'blue', 2),('Chair', 'red', 3), ('yizi', 'red', 1),('yizi', 'blue', 6)
GO
SELECT * FROM tt.dbo.voc
GO
SELECT item, color, SUM(quantity) AS Qt
FROM tt.dbo.voc
GROUP BY CUBE(item, color) -- CUBE 所选中列中值的所有组合的聚合
GO
select item, color, sum(quantity) as qtsum
from tt.dbo.voc
group by item, color -- vs
- ROLLUP运算符
返回当前粒度及其以下级别的聚合
-- 返回 item | item + color
-- 不会再有次一粒度的color
select item, color, SUM(quantity) as Qt_sum
from tt.dbo.voc
group by rollup(item, color)
- GROUPING函数(区分空值&汇总值)
用于区分ROLLUP | CUBE | GROUPING SETS产生的空值与标准空值。如果列值来自实际数,则返回0;如果列值来自CUBE | ROLLUP | GROUPING SETS操作则生成NULL,返回1.
-- 区分事实数据产生的NULL & CUBE|ROLLUP产生的NULL
SELECT CASE WHEN (GROUPING(item) = 1) THEN '汇总' -- CUBE|ROLLUP NULLELSE ISNULL(item, '未知') -- 事实数据 NULLEND AS item, CASEWHEN (GROUPING(color) = 1) THEN '汇总'ELSE ISNULL(color, '未知')END AS color, SUM(quantity) as Qt_sum
FROM tt.dbo.voc
GROUP BY CUBE(item, color)
--HAVING item = 'Chair'
-- AND color IS NULL
- GROUPING SETS
书中这点没讲清楚,查看官网资料补充。
GROUPING SETS选项使您能够将多个GROUP BY子句组合为一个GROUP BY子句。结果等于指定组的UNION ALL。
例如,GROUP BY ROLLUP (Country, Region)
&GROUP BY GROUPING SETS ( ROLLUP (Country, Region) )
返回相同的结果。
当GROUPING SETS具有两个或多个元素时,结果是元素的并集
SQL不会合并为GROUPING SETS列表生成的重复组。例如,在中GROUP BY ( (), CUBE (Country, Region) ),两个元素都返回总计的一行,并且这两行将在结果中列出。
-- 返回相同的结果
SELECT item, color, SUM(quantity) AS Qt_sum
FROM tt.dbo.voc
GROUP BY CUBE(item, color)
GO
SELECT item, color, SUM(quantity) AS Qt_sum
FROM tt.dbo.voc
GROUP BY GROUPING SETS(CUBE(item, color))
7.其它
7.1 在其它语句中使用UNION、EXCEPT、INTERSECT语句限制
- 第1个SELECT语句中可以包含一个INTO子句1,保存结果集,其它不可
- GROUP BY和HAVING子句只能在各个子句中起作用
7.2 突破结果集操作限制
通过临时表、派生表2、辅助列、公用表表达式(CTE)来过渡
INTO语句指定结果集存储位置
select * into #T1 from T1
↩︎ ↩︎派生表
-- eg.派生表 SELECT col FROM ( SELECT * FROM T1UNIONSELECT * FROM T2) tt GROUP BY col
↩︎
MSSQL_8 操作结果集相关推荐
- 如何创建一个用户、授权操作k8s集群的过程?
本篇带给大家如何创建一个用户.授权操作k8s集群的过程.希望对你有所帮助! 背景 172.16.99.128是的我k8s集群的master节点,此处是从这里获取集群的证书. 创建访问architech ...
- Android Studio相见恨晚的操作锦集
作为一个Android开发者,最常使用的就是Android Studio了,我在这里声明Android Studio比Eclipse好用100倍,不服来辩.本文用于纪录Android Studio中相 ...
- Linux信号 五 信号挂起与信号掩码操作接口集
A signal may be blocked, which means that it will not be delivered until it is later unblocked. Betw ...
- sql查询两个表结果相减_SQL 操作结果集 -并集、差集、交集、结果集排序
操作结果集 为了配合测试,特地建了两个表,并且添加了一些测试数据,其中重复记录为东吴的人物. 表:Person_1魏国人物 表:Person_2蜀国人物 A.Union形成并集 Union可以对两个或 ...
- python操作redis集群_python 连接管理作redis集群
python的redis库是不支持集群操作的,推荐库:redis-py-cluster. 安装 pip3 install redis-py-cluster 连接redis集群 #!/usr/bin/e ...
- 数据库应用----Mongodb 4.0 版本 基础操作---复制集,选举方法、部署认证 (二)
Mongodb 4.0 版本 基础操作-复制集,选举方法.部署认证 (二) 文章目录 Mongodb 4.0 版本 基础操作---复制集,选举方法.部署认证 (二) 一.MongoDB 复制集 二.部 ...
- 中南大学材料院matlab考试题,中南大学材料院matlab操作题集答案
中南大学材料院matlab操作题集答案 的 491 操作题集 操作题1 <Matlab与科学计算>P28 例2.1 要求计算水在温度为0℃,20℃,40℃,60℃,80℃时的黏度,已知水的 ...
- python 操作redis集群
python 操作redis集群 一.连接redis集群 python的redis库是不支持集群操作的,推荐库:redis-py-cluster,一直在维护.还有一个rediscluster库,看Gi ...
- 在IDEA中创建maven项目编写java代码操作HDFS集群
一.安装win10编译过的hadoop 1.将编译好的hadoop包放在非中文目录 2.配置HADOOP_HOME环境变量 3.将hadoop包的bin目录加到PATH环境变量中 二.在idea中创建 ...
- redis的hash操作在集中式session中的应用
在集群部署时,为了高可用性的目的,往往把session进行共享,共享分为两种:session复制和集中式管理. redis在session集中式管理中可以起到比较大的作用. 制约session集中式共 ...
最新文章
- 智源重大研究方向“智能信息检索与挖掘”发布会(活动报名)
- RTX 3090 AI性能实测:FP32训练速度提升50%,张量核心缩水
- 通过severlet获取请求头信息
- VS2008如何自动添加消息映射
- 北斗导航 | 多模多频实时GNSS软件接收机
- OpenGL ES之GLSL实现索引绘制及渲染纹理和颜色混合
- 事件捕获(capture)和冒泡事件(Bubble)
- 使用IntelliJ IDEA和Maven管理搭建+Web+Tomcat开发环境
- GitHub|基于强化学习自动化剪枝
- linux开放mysql远程连接_Linux开启MySql远程连接
- oracle scn与数据恢复,Oracle数据恢复:数据文件头的SCN与时间校验
- java 解析xml文件
- lLinux编程大全
- 人人接龙助手,三分钟为你的微信群创建打卡活动
- BCR-ABL融合基因及检测
- wamp5环境配置基础教程
- 关于GNS3常用命令
- PHP 获取网页内容的三种方法
- 五脚18.8数码管显示
- 2022年全球与中国EV继电器市场现状及未来发展趋势