当前位置:网站首页>一个很少见但很有用的SQL功能
一个很少见但很有用的SQL功能
2022-08-02 21:49:00 【wadfdhsajd】
我最近偶然发现了一个标准的SQL特性,令我惊讶的是,这个特性在HSQLDB中实现了。这个关键字是CORRESPONDING
,它可以和所有的集合操作一起使用,包括UNION
、INTERSECT
、和EXCEPT
。
让我们来看看sakila数据库。它有3个表,里面都是人:
CREATE TABLE actor (
actor_id integer NOT NULL PRIMARY KEY,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
last_update timestamp
);
CREATE TABLE customer (
customer_id integer NOT NULL PRIMARY KEY,
store_id smallint NOT NULL,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
email varchar(50),
address_id smallint NOT NULL,
create_date date NOT NULL,
last_update timestamp,
active boolean
);
CREATE TABLE staff (
staff_id integer NOT NULL PRIMARY KEY,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
address_id smallint NOT NULL,
email varchar(50),
store_id smallint NOT NULL,
active boolean NOT NULL,
username varchar(16) NOT NULL,
password varchar(40),
last_update timestamp,
picture blob
);
复制代码
相似,但不相同。如果我们想从我们的数据库中获得所有的 "人 "呢?在任何普通的数据库产品中,有一种方法可以做到这一点:
SELECT first_name, last_name
FROM actor
UNION ALL
SELECT first_name, last_name
FROM customer
UNION ALL
SELECT first_name, last_name
FROM staff
ORDER BY first_name, last_name
复制代码
结果可能看起来像这样:
|first_name|last_name|
|----------|---------|
|AARON |SELBY |
|ADAM |GOOCH |
|ADAM |GRANT |
|ADAM |HOPPER |
|ADRIAN |CLARY |
|AGNES |BISHOP |
|AL |GARLAND |
|ALAN |DREYFUSS |
|... |... |
复制代码
使用CORRESPONDING
现在,在HSQLDB中,以及在标准SQL中,你可以使用CORRESPONDING
来完成这种任务。比如说:
SELECT *
FROM actor
UNION ALL CORRESPONDING
SELECT *
FROM customer
UNION ALL CORRESPONDING
SELECT *
FROM staff
ORDER BY first_name, last_name
复制代码
其结果是这样的:
|first_name|last_name|last_update |
|----------|---------|-----------------------|
|AARON |SELBY |2006-02-15 04:57:20.000|
|ADAM |GOOCH |2006-02-15 04:57:20.000|
|ADAM |GRANT |2006-02-15 04:34:33.000|
|ADAM |HOPPER |2006-02-15 04:34:33.000|
|ADRIAN |CLARY |2006-02-15 04:57:20.000|
|AGNES |BISHOP |2006-02-15 04:57:20.000|
|AL |GARLAND |2006-02-15 04:34:33.000|
|ALAN |DREYFUSS |2006-02-15 04:34:33.000|
|... |... |... |
复制代码
那么,发生了什么?列FIRST_NAME
,LAST_NAME
, 和LAST_UPDATE
是这三个表所共有的。换句话说,如果你针对HSQLDB中的INFORMATION_SCHEMA
,运行这个查询:
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'ACTOR'
INTERSECT
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'CUSTOMER'
INTERSECT
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'STAFF'
复制代码
你得到的正是这3个列:
|COLUMN_NAME|
|-----------|
|FIRST_NAME |
|LAST_NAME |
|LAST_UPDATE|
复制代码
换句话说,CORRESPONDING
,在集合操作的子查询中创建列的交集(即 "共享列"),投影这些,并应用该投影的集合操作。在某种程度上,这类似于一个 [NATURAL JOIN](https://blog.jooq.org/impress-your-coworkers-with-a-sql-natural-full-outer-join/)
,后者也试图找到列的交集以产生一个连接谓词。然而,NATURAL JOIN
,然后投影所有的列(或列的联合),而不仅仅是共享的列。
使用CORRESPONDING BY
就像NATURAL JOIN
,这是个有风险的操作。只要一个子查询改变了它的投影(例如,由于表的列重命名),所有这些查询的结果也会改变,甚至可能不会产生语法错误,只是结果不同。
事实上,在上面的例子中,我们可能根本不关心那个LAST_UPDATE
列。它被意外地包含在UNION ALL
的集合操作中,就像NATURAL JOIN
会意外地使用LAST_UPDATE
来连接一样。
对于连接,我们可以使用JOIN .. USING (first_name, last_name)
,至少指定我们想通过哪一个共享列名来连接这两个表。使用CORRESPONDING
,我们可以为同样的目的提供可选的BY
子句:
SELECT *
FROM actor
UNION ALL CORRESPONDING BY (first_name, last_name)
SELECT *
FROM customer
UNION ALL CORRESPONDING BY (first_name, last_name)
SELECT *
FROM staff
ORDER BY first_name, last_name;
复制代码
现在,这只产生了两个想要的列:
|first_name|last_name|
|----------|---------|
|AARON |SELBY |
|ADAM |GOOCH |
|ADAM |GRANT |
|ADAM |HOPPER |
|ADRIAN |CLARY |
|AGNES |BISHOP |
|AL |GARLAND |
|ALAN |DREYFUSS |
|... |... |
复制代码
事实上,这样一来,我们甚至可以有意义地使用INTERSECT和EXCEPT的语法,例如,找到与某个演员共享名字的客户:
SELECT *
FROM actor
INTERSECT CORRESPONDING BY (first_name, last_name)
SELECT *
FROM customer
ORDER BY first_name, last_name;
复制代码
制作:
|first_name|last_name|
|----------|---------|
|JENNIFER |DAVIS |
复制代码
其他方言
我以前没有在其他方言中多次遇到过这种语法。也许,它在将来会运到PostgreSQL中。Vik Fearing已经在做一个分支了:
小伙伴们有兴趣想了解内容和更多相关学习资料的请点赞收藏+评论转发+关注我,后面会有很多干货。
我有一些面试题、架构、设计类资料可以说是程序员面试必备!所有资料都整理到网盘了,需要的话欢迎下载!私信我回复【07】即可免费获取
链接:https://juejin.cn/post/7126351838349099022
边栏推荐
猜你喜欢
宝塔搭建实测-基于ThinkPHP5.1的wms进销存源码
group of people
「X」to「Earn」:赛道现状与破局思路
ROS2初级知识(9):bag记录过程数据和重放
【使用pyside2遇到的问题】This application failed to start because no Qt platform plugin could be initialized.
Swin Transformer 论文精读,并解析其模型结构
The only way to go from a monthly salary of 10k to 30k: automated testing
FRED应用:激光二极管光源耦合到光纤的仿真
若依如何实现添加水印功能
JS Date 时间戳 getTune data.parse 倒计时小程序
随机推荐
行业 SaaS 微服务稳定性保障实战
Tanabata is here - the romance of programmers
工厂模式理解了没有?
虚拟内存 virualmemory
无线振弦采集仪远程修改参数的方式
软件测试笔试题1(附答案)
mysql 错误:The driver has not received any packets from the server.
圆锥折射作为偏振计量工具的模拟
我用这一招让团队的开发效率提升了 100%!
win10安全中心设置不扫描某个文件夹的方法
How to seize the new trend of NFT, yuan|universe|universe?
饥荒联机版Mod开发——制作简单的物品(三)
【TypeScript】深入学习TypeScript类(下)
【Unity】Unity开发进阶(六)UnityEvent使用与源码解析
Win10怎么开启自带的游戏录屏功能?
刚安装完win10专业工作站版,系统变量中Path默认值有哪些?重新建一个“PATH”变量名,会覆盖掉原先的“Path”。
创建型模式 - 单例模式Singleton
Flink优化的方方面面
go rand 包
RuoYi-App启动教程