目录

  • 合并结果集
  • 查询结果集的差异行
  • 查询结果集的相同行
  • 优先级(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增加了CUBEROLLUP参数。

  • 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)来过渡


  1. INTO语句指定结果集存储位置select * into #T1 from T1 ↩︎ ↩︎

  2. 派生表

    -- eg.派生表
    SELECT col
    FROM ( SELECT * FROM T1UNIONSELECT * FROM T2) tt
    GROUP BY col
    

    ↩︎

MSSQL_8 操作结果集相关推荐

  1. 如何创建一个用户、授权操作k8s集群的过程?

    本篇带给大家如何创建一个用户.授权操作k8s集群的过程.希望对你有所帮助! 背景 172.16.99.128是的我k8s集群的master节点,此处是从这里获取集群的证书. 创建访问architech ...

  2. Android Studio相见恨晚的操作锦集

    作为一个Android开发者,最常使用的就是Android Studio了,我在这里声明Android Studio比Eclipse好用100倍,不服来辩.本文用于纪录Android Studio中相 ...

  3. Linux信号 五 信号挂起与信号掩码操作接口集

    A signal may be blocked, which means that it will not be delivered until it is later unblocked. Betw ...

  4. sql查询两个表结果相减_SQL 操作结果集 -并集、差集、交集、结果集排序

    操作结果集 为了配合测试,特地建了两个表,并且添加了一些测试数据,其中重复记录为东吴的人物. 表:Person_1魏国人物 表:Person_2蜀国人物 A.Union形成并集 Union可以对两个或 ...

  5. python操作redis集群_python 连接管理作redis集群

    python的redis库是不支持集群操作的,推荐库:redis-py-cluster. 安装 pip3 install redis-py-cluster 连接redis集群 #!/usr/bin/e ...

  6. 数据库应用----Mongodb 4.0 版本 基础操作---复制集,选举方法、部署认证 (二)

    Mongodb 4.0 版本 基础操作-复制集,选举方法.部署认证 (二) 文章目录 Mongodb 4.0 版本 基础操作---复制集,选举方法.部署认证 (二) 一.MongoDB 复制集 二.部 ...

  7. 中南大学材料院matlab考试题,中南大学材料院matlab操作题集答案

    中南大学材料院matlab操作题集答案 的 491 操作题集 操作题1 <Matlab与科学计算>P28 例2.1 要求计算水在温度为0℃,20℃,40℃,60℃,80℃时的黏度,已知水的 ...

  8. python 操作redis集群

    python 操作redis集群 一.连接redis集群 python的redis库是不支持集群操作的,推荐库:redis-py-cluster,一直在维护.还有一个rediscluster库,看Gi ...

  9. 在IDEA中创建maven项目编写java代码操作HDFS集群

    一.安装win10编译过的hadoop 1.将编译好的hadoop包放在非中文目录 2.配置HADOOP_HOME环境变量 3.将hadoop包的bin目录加到PATH环境变量中 二.在idea中创建 ...

  10. redis的hash操作在集中式session中的应用

    在集群部署时,为了高可用性的目的,往往把session进行共享,共享分为两种:session复制和集中式管理. redis在session集中式管理中可以起到比较大的作用. 制约session集中式共 ...

最新文章

  1. 智源重大研究方向“智能信息检索与挖掘”发布会(活动报名)
  2. RTX 3090 AI性能实测:FP32训练速度提升50%,张量核心缩水
  3. 通过severlet获取请求头信息
  4. VS2008如何自动添加消息映射
  5. 北斗导航 | 多模多频实时GNSS软件接收机
  6. OpenGL ES之GLSL实现索引绘制及渲染纹理和颜色混合
  7. 事件捕获(capture)和冒泡事件(Bubble)
  8. 使用IntelliJ IDEA和Maven管理搭建+Web+Tomcat开发环境
  9. GitHub|基于强化学习自动化剪枝
  10. linux开放mysql远程连接_Linux开启MySql远程连接
  11. oracle scn与数据恢复,Oracle数据恢复:数据文件头的SCN与时间校验
  12. java 解析xml文件
  13. lLinux编程大全
  14. 人人接龙助手,三分钟为你的微信群创建打卡活动
  15. BCR-ABL融合基因及检测
  16. wamp5环境配置基础教程
  17. 关于GNS3常用命令
  18. PHP 获取网页内容的三种方法
  19. 五脚18.8数码管显示
  20. 2022年全球与中国EV继电器市场现状及未来发展趋势

热门文章

  1. 七、torch.nn
  2. P1296 分形宇宙
  3. 如何将手机中的Word文档转换成PDF文件?
  4. Win10 设置系统还原点
  5. java使用d3_D3 快速入门指北
  6. 微信小程序直接打开文件操作(pdf)
  7. 计算机主机usb端口使用不了,解答电脑usb接口不能用怎么解决
  8. 数据有效性跨表引用的解决
  9. 实现Excel单元格中的下拉选项和数据有效性
  10. ESX4 安装前的考虑