首页 > 数据库 >SQL集合操作Union实现

SQL集合操作Union实现

时间:2023-08-01 14:02:32浏览次数:63  
标签:Union TEXT SQL 元组 INTERSECT PLAIN 集合


Union的语义是把两部分查询的结果合并起来,最终结果的列名和类型定义与第一个查询一致。Union语句可以是Union All或者Union Distinct,默认情况下最好采用前者,即只有Union关键字时等价于Union All。下面看看Union All/Union Distinct的例子。

表A       表B

1

2

3

4

3

4

3

4

5

6

3

4

3

4

7

8

 

 

 

UnionAll

1

2

3

4

3

4

3

4

5

6

3

4

3

4

7

8

 

UnionDistinct

1

2

3

4

5

6

7

8


MergeUnion

ALL

如果是Union All,那么MergeUnion的两个输入表没有必要是有序的,MergeUnion只需要先输出第一个表的数据,再输出第二个表的数据就可以了。

Distinct

如果是Union Distinct,MergeUnion算法要求两个输入表数据都有相同的排序。假设两个输入表的行数分别为M、N,则MergeUnion算法复杂度为O(M+N)。

具体实现如下:

1.        如果第一个表的当前元组小于第二个表的当前元组,或者第二个表结束,那么输出第一个表的元组,且跳过相等的元组。

2.        如果第一个表的当前元组大于第二个表的当前元组,或者第一个表结束,那么输出第二个表的元组,且跳过相等的元组。

3.        如果第一个表的当前元组等于第二个表的当前元组,那么输出第一个表的元组,且跳过第一个和第二个表的相同元组。

4        如果两个表都结束,则返回结束。



其余思想类似。前提都是需要排序。不排序,则可以采用Hash的思路。思路见SQL Distinct的实现



-----


附SQL集合运算 差集 并集 交集的入门介绍:


SQL集合运算 差集 并集 交集


SQL-3标准中提供了三种对检索结果进行集合运算的命令:并集UNION;交集INTERSECT;差集EXCEPT(在Oracle中叫做 MINUS)。在有些数据库中对此的支持不够充分,如MySql中只有UNION,没有其他两种。实际上这些运算都可以通过普通的SQL来实现,虽然有时有些繁琐。

假设有两个表(或视图)s,t,s中有两个字段sa,sb;t中有两个字段ta,tb;

差集EXCEPT:



PLAIN TEXT



SQL:

  1. SELECTsaFROMs
  2. EXCEPT
  3. SELECTtaFROMt;



可以写作



PLAIN TEXT



SQL:

  1. SELECTsaFROMs
  2. WHEREsaNOTIN
  3. (SELECTtaFROMt)



上面的例子中忽略了对s和t单独的条件,这些总可以加入AND条件完成,或者使用视图。如果是多个字段比较麻烦,如:



PLAIN TEXT



SQL:

  1. SELECTsa, sbFROMs
  2. EXCEPT
  3. SELECTta, tbFROMt;



需要写成



PLAIN TEXT



SQL:

  1. SELECTsa, sbFROMs
  2. WHERE(sa, sb)NOTIN
  3. (SELECTta, tbFROMt)



 

上面使用的语法不见得数据库都支持。好在不支持EXCEPT的MySQL支持这种语法,而不支持这种语法的MSSQL又支持EXCEPT。

注意对于这样的row constructors(Mysql术语),是和下面写法(以及其他类似写法)不等价的。



PLAIN TEXT



SQL:

  1. SELECTsa, sbFROMs
  2. WHEREsaNOTIN
  3. (SELECTtaFROMt)
  4. ANDsbNOTIN
  5. (SELECTtbFROMt)



在MSSQL中的一个解决技巧是,把这两个字段(假设字符类型)拼起来,即



PLAIN TEXT



SQL:

  1. SELECTsa, sbFROMs
  2. WHEREsa+sbNOTIN
  3. (SELECTta+tbFROMt)



 

交集INTERSECT:



PLAIN TEXT



SQL:

  1. SELECTsaFROMs
  2. INTERSECT
  3. SELECTtaFROMt;



可以写成



PLAIN TEXT



SQL:

  1. SELECTsaFROMs
  2. WHEREsa IN
  3. (SELECTtaFROMt)



当然也可以写成



PLAIN TEXT



SQL:

  1. SELECTsaFROMs
  2. WHEREEXISTS
  3. (SELECT*FROMtWHEREt.ta=s.sa)



或者使用连接



PLAIN TEXT



SQL:

  1. SELECTsaFROMs, t
  2. WHEREsa = ta



 

实际上这几个语句都有点问题,就是INTERSECT在出现重复时的语义问题。按照SQL-3标准,类似UNION,可以有明确的 INTERSECT ALL或者INTERSECT DISTINCT语法。一般的INTERSECT实现并没有明确这一点,而且从逻辑上讲意义也不大。那么当s或t中出现重复的时,如sa='x'的有2 个,sb='x'的有3个,使用上面的子查询将返回2行,使用连接将返回6行,当然这两个语句都可以加上一个DISTINCT,就实现了 INTERSECT DISTINCT语义了。

并集UNION:

MySql从4.0开始就支持UNION(ALL 和 DISTINCT)了,为完整起见,也列举一下。
其实实现这样一个结果是很麻烦的



PLAIN TEXT



SQL:

  1. SELECTsaFROMs
  2. DISTINCT
  3. SELECTtaFROMt;



需要使用外连接,而且是Full的外连接



PLAIN TEXT



SQL:

  1. SELECTDISTINCTNVL(s.sa, t.ta)
  2. FROMs FULLOUTERJOINtON(s.sa=t.ta)



 

上面的例子中我使用了Oracle的语法,实际上MySql不支持FULL OUTER JOIN(虽然支持LEFT和RIGHT OUTER JOIN),好在MySql支持UNION。

对于UNION ALL语义,我还没有想出来用普通查询如何实现,如果在上面语句中去掉DISTINCT,结果肯定不对。



标签:Union,TEXT,SQL,元组,INTERSECT,PLAIN,集合
From: https://blog.51cto.com/maray/6921040

相关文章

  • Java集合框架
    Java集合框架集合框架用于存储数据的容器,集合框架是为表示和操作集合而规定的一种统一的标准的体系结构任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法接口表示集合的抽象数据类型。接口允许我们操作集合时不必关注具体实现,从而达到“多态......
  • 理解MySQL——索引与优化
    写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点。考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储100条记录。如果没有索引,查询将对整个表进行扫描,最坏的情况下,如果所有数据页都不在内存,需要读取10^4个页面,如果这10^4个页......
  • 智慧校园源码:vue2+Java+springboot+MySQL+elmentui+jpa+jwt
    智慧校园综合管理云平台源码系统主要以校园安全、智慧校园综合管理云平台为核心,以智慧班牌为学生智慧之窗,以移动管理平台、家校沟通为辅。教师—家长一学校—学生循环的无纸化管理模式及教学服务,实现多领域的信息互联互通以及校园管理一体化、信息数据化、数据自动化。智慧班牌融合......
  • SQL优化系列之 in与range 查询
    《高性能MySQL》 里面提及用in这种方式可以有效的替代一定的range查询,提升查询效率,因为在一条索引里面,range字段后面的部分是不生效的(ps.需要考虑ICP)。MySQL优化器将in这种方式转化成 n*m 种组合进行查询,最终将返回值合并,有点类似union但是更高效。MySQL在IN()组合条件过多......
  • 导入mysql 乱码问题及 Linux 中的文件格式转换
    问题下载了一个单词sql文件,导入mysql报错,查看文件类型:%fileenglish_word.sqlenglish_word.sql:Non-ISOextended-ASCIItext与另一个导入成功的文件对比,发现格式不一样:%fileenglish-root.sqlenglish-root.sql:UTF-8Unicodetext,withverylonglines,withnoli......
  • MySQL8压缩包安装教程
    解压缩包配置环境变量初始化mysqld--initialize-insecure安装服务mysqldinstallMySQL8移除服务mysqldremoveMySQL8启动服务netstartMySQL8修改密码切换数据库usemysql;修改root用户的密码alteruser'root'@localhostidentifiedby'mysql';刷新权限,一般......
  • liunx 环境 mysql5.6安装
    1安装包下载mysql5.6下载地址:http://dev.mysql.com/downloads/mysql/ 这里选择Linux版本:使用Navicat管理远程Linux服务器上的MySQL数据库 http://www.linuxidc.com/Linux/2011-09/42285.htm ftp://mirror.switch.ch/mirror/mysql/Downloads/MySQL-5.6/2mysql的安装从官网下载......
  • MySQL中动态SQL的解决方法:预处理语句
    动态SQL是一种很好的特性,允许开发人员在运行时动态构建和执行SQL语句。虽然MySQL缺乏对动态SQL的内置支持,但本文介绍了使用预处理语句(preparedstatements)的变通方法。将探讨如何利用预处理语句实现动态查询执行、参数化查询以及动态表和列查询。 了解预处理语句(preparedst......
  • SAS 编程技巧 - PROC SQL(二)
    上一节中,我们介绍了如何使用SQL创建和删除数据集、视图和索引。这一节我们介绍如何使用SQL修改数据集的结构和更新数据集中的数据。修改数据集结构使用ALTERTABLE可以修改数据集的结构,包括增加、删除变量、修改变量属性,以及对数据完整性约束(integrityconstraints)的操作......
  • docker 不适合MySQL
    近几年Docker非常的火热,各位开发者恨不得把所有的应用、软件都部署在Docker容器中,但是您确定也要把数据库也部署的容器中吗?这个问题不是子虚乌有,因为在网上能够找到很多各种操作手册和视频教程,这里整理了一些数据库不适合容器化的原因供大家参考,同时也希望大家在使用时能够谨慎一......