你需要的每一个 SQL 连接

2025-06-07

你需要的每一个 SQL 连接

好吧……也许不是每次连接都用。但这张速查表帮助我在数据库 101 期中考试中获得了 104% 的成绩,所以它一定很有价值。

注意:很多标记我无法在 dev.to 上进行。所以,虽然我允许这篇文章完整地交叉发布,但如果没有“请注意!”的背景高亮、文本内的交叉链接、目录等,我在文中提到的很多内容就变得毫无意义了。

我建议在我的原始博客上阅读它,而不是在 dev.to 上,然后再回到 dev.to 进行讨论!


我费了好大劲才找到我以前的学校笔记,因为我当时甚至都没在标题里加“连接”这个词。我把笔记命名为“SQL 中的集合运算”。这才是真正的重点,因为无论你用 SQL、Excel VLOOKUP、Python,还是用纸笔来比较一个记录列表和另一个记录列表,都无关紧要。把一个“集合”和另一个“集合”结合起来,作为一个商业问题,就是数学。更棒的是,这是有趣的数学,而不是难懂的数学!这就是维恩图——那种让你像小学学生一样随心所欲涂鸦的数学。

SQL 代码有助于了解您的业务问题需要合并的两组记录(每条“记录”代表现实世界中的某个实体,例如一个人、一张发票或一个国家/地区)是否位于同一个关系数据库管理系统 (RDBMS)中,通常简称为“数据库”。所有此类系统都具备使用 SQL 编程语言提取数据的功能。

  • 如果您是Python数据分析师,请务必学习一些 SQL,以便您可以利用其功能对数据所在的数据库进行处理。

  • 如果您是Salesforce分析师或系统管理员,您可能遇到过报表和 SOQL 的限制。也许您通过将两个表导出到 Excel,然后执行VLOOKUP操作来连接它们来解决这些问题。为了更上一层楼,您可能想探索 Python,而不是 SQL——除非您的 IT 部门已经将 Salesforce 组织的数据备份到传统数据库。那么您需要了解有关 SQL 的所有信息,因为它将为您节省大量时间!

我经常使用 Oracle 数据库,因此我发现 Oracle 风格的 SQL 代码输入速度最快,因此我将以此为例进行说明。您可以注册一个免费账户并试用他们的Live SQL工具,在线运行 Oracle SQL 代码。

要将其转化为另一种“风格”的 SQL,你可能需要用 Google 搜索我使用的关键词,并结合你的数据库名称。例如,当我的full outer join命令在 MySQL 数据库中无法使用时,我谷歌搜索了“'full outer join' mysql”,结果发现 MySQL 风格的 SQL 并不包含任何full outer join命令。相反,你必须巧妙地组合一些较小的集合运算 (这就像在维恩图中,一次仔细地涂满整个圆圈,而不是用蜡笔一次涂满整个图)

专业提示:收藏本文并将其作为参考指南。

无论您对 SQL 了解多少,都可以使用本文顶部的目录一次阅读一个部分。

  • 本指南虽然简单,但篇幅较长,所以如果你正在学习,建议每天阅读一种“加入类型”。(除非你要坐长途巴士!)
  • 如果您了解基本知识并且只需要比较命令,请直接跳到您感兴趣的命令。

我们的样本数据

表“ A”内容(CONVENTION

CONVENTION是参加会议的人员及其工作地点的列表。

(是的,这是一个非常八卦的活动,要求参加者提供社会安全号码。)

社会安全号码 名称_lf 酸碱度 em 公司
A1A1A1 阿姆吉特·阿努什 1111111 111@example.com 苹果
B2B2B 博尔赫斯,贝尼塔 2222222 222@example.com 布瓦龙
C3C3C3 凯茜·库姆斯 3333333 333@example.com CVS
D4D4D4 达赫尔,达尔维什 4444444 444@example.com 戴尔
E5E5E5 埃利斯,埃兹拉 5555555 555@example.com 法国电力公司
F6F6F6 弗朗西斯·富尔维娅 6666666 666@example.com 凡士通

表“ B”内容(RESTAURANT

RESTAURANT是餐厅常客的列表,包括他们最喜欢的食物以及他们的年龄。

(是的,这是一家非常爱管闲事的餐厅,会向常客询问社会安全号码。)

  • 请注意 Cathy Combs 的电子邮件地址是“ccc”,而不是“333”。
  • 请注意 Frances Fulvia 的社会保障号码中的拼写错误。
社会的 名称_fl 电话 电子邮件 最喜欢的食物 年龄
C3C3C3 凯茜·库姆斯 3333333 ccc@example.com 胡萝卜 33
D4D4D4 达维什·达赫尔 4444444 444@example.com 多力多滋 四十四
E5E5E5 埃兹拉·埃利斯 5555555 555@example.com 菊苣 55
FFF666 弗朗西丝·富尔维亚 6666666 666@example.com 薯条 66
G7G7G7 7777777 777@example.com 77
H8H8H8 海伦·霍珀 8888888 888@example.com 鹰嘴豆泥 88

创建此数据的代码(“DDL”和“DML”)

如果您想亲自尝试,这里有在 Oracle 数据库中创建表并使用我们的示例数据填充它们的代码CONVENTIONRESTAURANT

drop table CONVENTION;
create table CONVENTION ( 
    ssn     varchar2(6) not null 
    , name_lf   varchar2(30) not null 
    , ph        varchar2(7) not null 
    , em        varchar(15) not null 
    , company   varchar(15) not null 
);
insert into CONVENTION values ('A1A1A1', 'Amjit, Anush', '1111111', '111@example.com', 'Apple');
insert into CONVENTION values ('B2B2B2', 'Borges, Benita', '2222222', '222@example.com', 'Boiron');
insert into CONVENTION values ('C3C3C3', 'Combs, Cathy', '3333333', '333@example.com', 'CVS');
insert into CONVENTION values ('D4D4D4', 'Daher, Darweesh', '4444444', '444@example.com', 'Dell');
insert into CONVENTION values ('E5E5E5', 'Ellis, Ezra', '5555555', '555@example.com', 'EDF');
insert into CONVENTION values ('F6F6F6', 'Fulvia, Frances', '6666666', '666@example.com', 'Firestone');
drop table RESTAURANT;
create table RESTAURANT ( 
    social      varchar2(6) not null 
    , name_fl   varchar2(30) not null 
    , phone     varchar2(7) not null 
    , email     varchar2(15) not null 
    , fav_food  varchar2(10) not null 
    , age       int not null 
);
insert into RESTAURANT values ('C3C3C3', 'Cathy Combs', '3333333', 'ccc@example.com', 'Carrots', 33);
insert into RESTAURANT values ('D4D4D4', 'Darweesh Daher', '4444444', '444@example.com', 'Doritos', 44);
insert into RESTAURANT values ('E5E5E5', 'Ezra Ellis', '5555555', '555@example.com', 'Endives', 55);
insert into RESTAURANT values ('FFF666', 'Frances Fulvia', '6666666', '666@example.com', 'Fries', 66);
insert into RESTAURANT values ('G7G7G7', 'Grace Gao', '7777777', '777@example.com', 'Garlic', 77);
insert into RESTAURANT values ('H8H8H8', 'Helen Hopper', '8888888', '888@example.com', 'Hummus', 88);
Enter fullscreen mode Exit fullscreen mode

谁重叠以及如何重叠

假设我们是一家大公司。规模如此之大,我们既经营会议,又拥有餐厅。我们想找出两家客户名单之间的“重叠部分”,并进行相应的分析。

实际上,关于我为什么选择这些查询和输出,我只想说这些。它们根本没有任何商业意义。我选择它们是为了演示不同风格的 SQL 查询能做什么和不能做什么!

但回到组合我们的集合的事情上:

一如既往,在比较来自两个不同数据集的“人员”记录时,必须确定什么才能“证明”两条记录代表同一个“现实世界的人”。姓名匹配吗?邮箱匹配吗?社会保障号匹配吗(记住,这些信息在人们去世后会被重复使用)?还是以上几种信息的组合?

对于我们的例子,我们将研究两种不同的数据组合方式,只是为了展示我们的代码能力。

在阅读代码之前,请务必查看CONVENTIONRESTAURANT注意:

  1. 当我们加入时A.ssn=B.social,Cathy-Ezra (3-5) 比赛
    • Anush、Benita 和“Frances w/ ssnF6F6F6”仍然是CONVENTION
    • “Frances w/ ssnFFF666”,Grace 和 Helen 仍然是独一无二的RESTAURANT
  2. 当我们加入时A.ph=B.phone and A.em=B.email,Darweesh-Frances (4-6) 比赛
    • Anush、Benita 和“Cathy w/ em 333@ ...”仍然是CONVENTION
    • “Cathy w/ email ccc@ ...”,Grace 和 Helen 仍然是独一无二的RESTAURANT

您已完全了解情况!让我们来看看 5 种“加入类型”中的第一个。


加入类型:“In A

维恩图,左侧圆圈为阴影,包括重叠部分

对于这种连接类型,我们预计有 6 行输出(Anush-Frances——来自的所有人CONVENTION)。

如果这些人中的任何一个“也存在”于RESTAURANT (根据我们选择的“匹配标准”的定义),我们希望从中看到关于他们的详细信息RESTAURANT

LEFT OUTER JOIN

SQL 查询,left outer join示例 1/4

首先,我们将根据社会保障号码进行匹配,因此 Cathy 有“表 B”中的详细信息,但 Frances 没有。

select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A
left outer join RESTAURANT B on A.ssn = B.social;
Enter fullscreen mode Exit fullscreen mode

查询输出,left outer join示例 1/4

名称_lf 公司 名称_fl 最喜欢的食物
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
凯茜·库姆斯 CVS 凯茜·库姆斯 胡萝卜
达赫尔,达尔维什 戴尔 达维什·达赫尔 多力多滋
埃利斯,埃兹拉 法国电力公司 埃兹拉·埃利斯 菊苣
弗朗西斯·富尔维娅 凡士通

SQL 查询,left outer join示例 2/4

接下来,我们将通过电话和电子邮件进行匹配,因此 Frances 有“表 B”的详细信息,但 Cathy 没有。)

select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A
left outer join RESTAURANT B on A.ph = B.phone and A.em = B.email;
Enter fullscreen mode Exit fullscreen mode

查询输出,left outer join示例 2/4

名称_lf 公司 名称_fl 最喜欢的食物
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
凯茜·库姆斯 CVS
达赫尔,达尔维什 戴尔 达维什·达赫尔 多力多滋
埃利斯,埃兹拉 法国电力公司 埃兹拉·埃利斯 菊苣
弗朗西斯·富尔维娅 凡士通 弗朗西丝·富尔维亚 薯条

SQL 查询,left outer join示例 3/4

接下来,我们将尝试(错误地)抑制50 岁以下任何人的详细信息name_flfav_food

select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A
left outer join RESTAURANT B on A.ssn = B.social
where B.age >= 50;
Enter fullscreen mode Exit fullscreen mode

查询输出,left outer join示例 3/4

名称_lf 公司 名称_fl 最喜欢的食物
埃利斯,埃兹拉 法国电力公司 埃兹拉·埃利斯 菊苣

笔记

尽管B在我们的连接中“来自”的行是可选的,但在添加过滤器时B,我们实际上将这个“左连接”变成了“内连接”,其中我们的数据必须出现在两个中。

我们实际上所做的是过滤掉没有年龄(因为他们不在表中B或年龄小于 50 的人的全部记录。

这是一个常见错误。我们将在下一个示例中修复它。

在数学中,当你将数字相减时,相减的顺序很重要。

同样,在使用 SQL 解决业务问题时,考虑“连接”和“过滤”数据的顺序也很重要。

SQL 查询,left outer join示例 4/4

现在我们实际上将抑制50 岁或以下任何人的name_fl详细fav_food信息。

select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A
left outer join (select * from RESTAURANT where age >= 50) B on A.ssn = B.social;
Enter fullscreen mode Exit fullscreen mode

查询输出,left outer join示例 4/4

名称_lf 公司 名称_fl 最喜欢的食物
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
凯茜·库姆斯 CVS
达赫尔,达尔维什 戴尔
埃利斯,埃兹拉 法国电力公司 埃兹拉·埃利斯 菊苣
弗朗西斯·富尔维娅 凡士通

笔记

在我们更正后的查询中,我们在将其视为之前按年龄进行了预过滤 ,这解决了上一个示例中的问题。RESTAURANTB

这是第一个“连接类型”。我们来看看第二个。


连接类型:“在A但不在B

维恩图,仅左侧圆圈不重叠的部分用阴影表示

对于这种连接类型,我们期望有 3 行输出(Anush+Benita+Cathy 或 Anush+Benita+Frances,取决于我们选择的“匹配标准”)

根据定义,表格B不是您的业务问题的最终输出的一部分,因此请记住,以下所有方法都只包含表格中的“详细信息” A

NOT IN

SQL 查询,not in示例 1/3

not in当你只匹配一列时就很好了。

select A.name_lf, A.company
from CONVENTION A
where A.ssn not in ( select B.social from RESTAURANT B );
Enter fullscreen mode Exit fullscreen mode

查询输出,not in示例 1/3

名称_lf 公司
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
弗朗西斯·富尔维娅 凡士通

SQL 查询,not in示例 2/3

not in当您需要匹配多个列时,就会变得危险——您必须将多个列连接成一个列,并负责任地处理空白/空值。

对于多列匹配,不是推荐的做法NOT EXISTS。请使用。

此查询仅供展示!

select A.name_lf, A.company
from CONVENTION A
where nvl(A.ph,'')||'~'||nvl(A.em,'') not in ( select nvl(B.phone,'')||'~'||nvl(B.email,'') from RESTAURANT B );
Enter fullscreen mode Exit fullscreen mode

查询输出,not in示例 2/3

名称_lf 公司
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
凯茜·库姆斯 CVS

SQL 查询,not in示例 3/3

我们的第三个not in示例甚至不是表之间的真正连接:请注意,它RESTAURANT甚至不在查询中。

我只是想指出,这种输入方式与not in您在向查询添加手动输入值过滤器时使用的方式相同。

select A.name_lf, A.company
from CONVENTION A
where A.ssn not in ( 'B2B2B2','XYZZY','E5E5E5' );
Enter fullscreen mode Exit fullscreen mode

查询输出,not in示例 3/3

名称_lf 公司
阿姆吉特·阿努什 苹果
凯茜·库姆斯 CVS
达赫尔,达尔维什 戴尔
弗朗西斯·富尔维娅 凡士通

<> ALL

这和完全一样not in,只是你输入的<> all是 。本节中的每个例子都not in可以用 来写<> all

SQL查询

select A.name_lf, A.company
from CONVENTION A
where A.ssn <> all ( select B.social from RESTAURANT B );
Enter fullscreen mode Exit fullscreen mode

查询输出

名称_lf 公司
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
弗朗西斯·富尔维娅 凡士通

MINUS

有了minus,我们就不能输出不符合我们的“匹配标准”的列。

也就是说,如果我们的业务问题是“仅出现在 中的所有值A”的简单“虚拟检查”列表,那么这种有限的输出可能就足够了。

SQL 查询,minus示例 1/2

select A.ssn
from CONVENTION A
minus
select B.social
from RESTAURANT B;
Enter fullscreen mode Exit fullscreen mode

查询输出,minus示例 1/2

社会安全号码
A1A1A1
B2B2B
F6F6F6

SQL 查询,minus示例 2/2

select A.ph, A.em
from CONVENTION A
minus
select B.phone, B.email
from RESTAURANT B;
Enter fullscreen mode Exit fullscreen mode

查询输出,minus示例 2/2

酸碱度 em
1111111 111@example.com
2222222 111@example.com
3333333 111@example.com

NOT EXISTS

如果您需要在复杂查询中使用多列“匹配条件”执行“in A,但不”,请使用此功能!B

where not exists (...)编写涉及多列匹配的“匹配条件”的复杂查询最有用的语法。

这种方法支持“进一步的过滤” ——只需将它们作为负责“匹配”操作的子句之外的A附加and子句即可。orwhere

如果其中有其余过滤器or,请务必使用括号,以确保您不会意外地将其变为where not exists (...)可选的。

SQL查询

SELECT A.name_lf, A.company
  FROM CONVENTION A
WHERE NOT EXISTS (
  SELECT NULL
    FROM RESTAURANT B
  WHERE A.ph = B.phone and A.em = B.email
);
Enter fullscreen mode Exit fullscreen mode

查询输出

名称_lf 公司
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
凯茜·库姆斯 CVS

LEFT OUTER JOIN ... B.... IS NULL

我实在想不出任何理由在实践中使用“LEFT OUTER JOIN加号B.joinColumn IS NULL”语法。它完全是过度使用。

但是...它在概念上与A要么同时存在B,要么同时存在”的常见方法相关,因此这是一个有趣的脑力练习,以确保您理解。

NOT EXISTS当您遇到没有语法的报告编写工具(例如Cognos Report StudioPython+Pandas时,熟悉它也是一种很好的“作弊”模式。

对于这种方法,对参与操作的所有列使用过滤器至关重要IS NULLBLEFT OUTER JOIN

否则,如果您的数据集中包含很多NULL值,您可能会得到意外的结果。

这种方法支持“进一步的过滤” ——只需将它们作为负责“匹配”操作的子句之外的A附加and子句即可。orwhere

如果其中有其余过滤器or,请务必使用括号,以确保您不会意外地将where ... is null过滤器变为可选的。

SQL查询

select A.name_lf, A.company
from CONVENTION A
left outer join RESTAURANT B on A.ph = B.phone and A.em = B.email
where B.phone is null
and B.email is null;
Enter fullscreen mode Exit fullscreen mode

查询输出

名称_lf 公司
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
凯茜·库姆斯 CVS

恭喜您完成了第二个“加入类型”。接下来是第三个!


连接类型:“在AB或两者中”

韦恩图,其中两个圆圈及其重叠处均有阴影

对于这种连接类型,我们期望输出 9 行(Anush-Helen,Cathy 或 Frances 加倍,取决于我们选择的“匹配标准”)

UNION

SQL 查询,union示例 1/2

select A.ssn
from CONVENTION A
union
select B.social
from RESTAURANT B;
Enter fullscreen mode Exit fullscreen mode

查询输出,union示例 1/2

社会安全号码
A1A1A1
B2B2B
C3C3C3
D4D4D4
E5E5E5
F6F6F6
FFF666
G7G7G7
H8H8H8
  • 您看到重复的“Frances”数据了吗?

笔记

与一样minus,我们不能输出不在我们的“匹配标准”中的列。

如果我们的业务问题是“来自任一表的所有可能值”的简单“虚拟检查”列表,则单列输出可能就足够了。

SQL 查询,union示例 2/2

select A.ph, A.em
from CONVENTION A
union
select B.phone, B.email
from RESTAURANT B;
Enter fullscreen mode Exit fullscreen mode

查询输出,union示例 2/2

酸碱度 em
1111111 111@example.com
2222222 222@example.com
3333333 333@example.com
3333333 ccc@example.com
4444444 444@example.com
5555555 555@example.com
6666666 666@example.com
7777777 777@example.com
8888888 888@example.com
  • 您看到重复的“Cathy”数据了吗?

FULL OUTER JOIN

SQL 查询,full outer join示例 1/2

select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A
full outer join RESTAURANT B on A.ssn = B.social;
Enter fullscreen mode Exit fullscreen mode

查询输出,full outer join示例 1/2

名称_lf 公司 名称_fl 最喜欢的食物
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
凯茜·库姆斯 CVS 凯茜·库姆斯 胡萝卜
达赫尔,达尔维什 戴尔 达维什·达赫尔 多力多滋
埃利斯,埃兹拉 法国电力公司 埃兹拉·埃利斯 菊苣
弗朗西斯·富尔维娅 凡士通
弗朗西丝·富尔维亚 薯条
海伦·霍珀 鹰嘴豆泥
  • 您看到重复的“Frances”数据了吗?

SQL 查询,full outer join示例 2/2

select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A
full outer join RESTAURANT B on A.ph = B.phone and A.em = B.email;
Enter fullscreen mode Exit fullscreen mode

查询输出,full outer join示例 2/2

名称_lf 公司 名称_fl 最喜欢的食物
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
凯茜·库姆斯 CVS
达赫尔,达尔维什 戴尔 达维什·达赫尔 多力多滋
埃利斯,埃兹拉 法国电力公司 埃兹拉·埃利斯 菊苣
弗朗西斯·富尔维娅 凡士通 弗朗西丝·富尔维亚 薯条
凯茜·库姆斯 胡萝卜
海伦·霍珀 鹰嘴豆泥
  • 您看到重复的“Cathy”数据了吗?

MySQL 伪造FULL OUTER JOIN

这就是我之前提到的巧妙的技巧,用来弥补 MySQL 风格的 SQL 没有full outer join命令这一事实。

SQL查询

select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A
left outer join RESTAURANT B on A.ssn = B.social
union
select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A
right outer join RESTAURANT B on A.ssn = B.social;
Enter fullscreen mode Exit fullscreen mode

查询输出

名称_lf 公司 名称_fl 最喜欢的食物
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
凯茜·库姆斯 CVS 凯茜·库姆斯 胡萝卜
达赫尔,达尔维什 戴尔 达维什·达赫尔 多力多滋
埃利斯,埃兹拉 法国电力公司 埃兹拉·埃利斯 菊苣
弗朗西斯·富尔维娅 凡士通
弗朗西丝·富尔维亚 薯条
海伦·霍珀 鹰嘴豆泥
  • 您看到重复的“Frances”数据了吗?

已经完成了一半了!继续阅读,了解第四种“连接类型”。

这个有很多选项,所以读起来会有点长。


连接类型:“A同时B

仅两个圆圈重叠部分用阴影表示的维恩图

对于这种连接类型,我们期望有 3 行输出(Cathy-Ezra 或 Darweesh-Frances,取决于我们选择的“匹配标准”)

IN

SQL 查询,in示例 1/3

select A.name_lf, A.company
from CONVENTION A
where A.ssn in ( select B.social from RESTAURANT B );
Enter fullscreen mode Exit fullscreen mode

查询输出,in示例 1/3

名称_lf 公司
凯茜·库姆斯 CVS
达赫尔,达尔维什 戴尔
埃利斯,埃兹拉 法国电力公司

笔记

  • in非常适合:
    • 你只匹配一列,并且
    • 你不需要查看或进一步过滤任何来自B

SQL 查询,in示例 2/3

select A.name_lf, A.company
from CONVENTION A
where nvl(A.ph,'')||'~'||nvl(A.em,'') in ( select nvl(B.phone,'')||'~'||nvl(B.email,'') from RESTAURANT B );
Enter fullscreen mode Exit fullscreen mode

查询输出,in示例 2/3

名称_lf 公司
达赫尔,达尔维什 戴尔
埃利斯,埃兹拉 法国电力公司
弗朗西斯·富尔维娅 凡士通

笔记

  • in当你需要匹配多列时,情况会变得棘手——你必须将多列连接成一列,并妥善处理空值/空值。对于多列匹配,这不是推荐的做法exists。请使用。这只是做个演示!

SQL 查询,in示例 3/3

select A.name_lf, A.company
from CONVENTION A
where A.ssn in ( 'B2B2B2','XYZZY','E5E5E5' );
Enter fullscreen mode Exit fullscreen mode

查询输出,in示例 3/3

名称_lf 公司
博尔赫斯,贝尼塔 布瓦龙
埃利斯,埃兹拉 法国电力公司

笔记

  • 这实际上并不是真正的表间连接:注意,这RESTAURANT甚至不在查询中。我只是想指出,这in与在查询中添加手动值过滤器时使用的方法相同。

= ANY

SQL查询

select A.name_lf, A.company
from CONVENTION A
where A.ssn = any ( select B.social from RESTAURANT B );
Enter fullscreen mode Exit fullscreen mode

查询输出

名称_lf 公司
凯茜·库姆斯 CVS
达赫尔,达尔维什 戴尔
埃利斯,埃兹拉 法国电力公司

笔记

和 完全一样in,只是你输入= any的是 。 中的 3 个例子均in适用。

INTERSECT

SQL 查询,intersect示例 1/2

select A.ssn
from CONVENTION A
intersect
select B.social
from RESTAURANT B;
Enter fullscreen mode Exit fullscreen mode

查询输出,intersect示例 1/2

社会安全号码
C3C3C3
D4D4D4
E5E5E5

笔记

minus和 一样union,我们不能输出不在我们的“匹配条件”中的列。

如果我们的业务问题是“出现在两个表中的所有值”的简单“虚拟检查”列表,那么单列输出可能就足够了。

SQL 查询,intersect示例 2/2

select A.ph, A.em
from CONVENTION A
intersect
select B.phone, B.email
from RESTAURANT B;
Enter fullscreen mode Exit fullscreen mode

查询输出,intersect示例 2/2

酸碱度 em
4444444 444@example.com
5555555 555@example.com
6666666 666@example.com

EXISTS

SQL查询

SELECT A.name_lf, A.company
  FROM CONVENTION A
WHERE EXISTS (
  SELECT NULL
    FROM RESTAURANT B
  WHERE A.ph = B.phone and A.em = B.email
);
Enter fullscreen mode Exit fullscreen mode

查询输出

名称_lf 公司
达赫尔,达尔维什 戴尔
埃利斯,埃兹拉 法国电力公司
弗朗西斯·富尔维娅 凡士通

笔记

  • existsin比你的“匹配标准”涉及多列时更好。
  • 类似于inexists不允许您查看或进一步过滤来自 的详细信息B

INNER JOIN

SQL查询

select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A
inner join RESTAURANT B on A.ph = B.phone and A.em = B.email;
Enter fullscreen mode Exit fullscreen mode

查询输出

名称_lf 公司 名称_fl 最喜欢的食物
达赫尔,达尔维什 戴尔 达维什·达赫尔 多力多滋
埃利斯,埃兹拉 法国电力公司 埃兹拉·埃利斯 菊苣
弗朗西斯·富尔维娅 凡士通 弗朗西丝·富尔维亚 薯条

={#equals}

连接表的简单=方法非常普遍,并且通常在使用 SQL 连接表的教程中首先讲授。

它支持“进一步的过滤”——只需将它们作为负责“匹配”操作的子句之外的附加and子句即可。orwhere

如果其中有其余过滤器or,请务必使用括号,以确保您不会意外地将“连接过滤器”变为可选项。

避免此类担忧是我稍微喜欢inner join=”方法的一个原因。

inner join当我需要尝试确定要编写的查询时,我几乎总是使用显式命令。这有助于我在玩游戏时避免不小心犯下退格错误。

SQL查询

select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A, RESTAURANT B
where A.ph = B.phone
and A.em = B.email;
Enter fullscreen mode Exit fullscreen mode

查询输出

名称_lf 公司 名称_fl 最喜欢的食物
达赫尔,达尔维什 戴尔 达维什·达赫尔 多力多滋
埃利斯,埃兹拉 法国电力公司 埃兹拉·埃利斯 菊苣
弗朗西斯·富尔维娅 凡士通 弗朗西丝·富尔维亚 薯条

近在咫尺,你就能尝到滋味了。还差一个——下面是第五种,也是最后一种“连接类型”。


连接类型:“A要么连接B,要么同时连接”

韦恩图,圆圈的独特部分用阴影表示,但没有重叠部分

对于这种连接类型,我们期望有 6 行输出(Anush+Benita+Cathy1+Cathy2+Grace+Helen 或 Anush+Benita+Frances1+Frances2+Grace+Helen,取决于我们选择的“匹配标准”) 。

虽然没有专门用于此连接类型的 SQL 命令,但请仔细查看表示它的维恩图。您能看出“In A,,, BOr Both”连接中“中间被咬掉的部分”吗?您的任务是编写代码来去除“中间被咬掉的部分”。

(附注:要把这个维恩图做成一块不会在数据库 101 课程期末考试时破碎的糖饼干是非常困难的。用 SQL 制作它要容易得多!)

选择你自己的冒险

根据以下架构设计查询,将重叠圆圈的“中间部分切掉”:

  1. 使用您最喜欢的方法构建“在AB或两者中”查询,并将其视为您的 A
  2. 使用您最喜欢的方法构建“In Both AAnd B查询,并将其视为您的 B
  3. 使用您最喜欢的“In But Not In 方法将您的新内容A和新内容缝合在一起。BAB

FULL OUTER JOIN ... A.... IS NULL OR B.... IS NULL

使用这种方法时,对涉及操作的所有列和的所有列使用过滤器至关重要IS NULLABFULL OUTER JOIN

否则,如果您的数据集中包含很多NULL值,您可能会得到意外的结果。

当您执行此操作时,“ AND”一起筛选来自同一个表的列,但“ OR”一起筛选来自不同表的列,如下面的示例代码所示。

这种方法支持“进一步的过滤”——只需将它们作为负责“匹配”操作的子句之外的附加and子句即可。orwhere

确保将... or ...负责“从中间咬一口”的整个过滤器括在其自己的括号中,以避免出现意外行为。

如果其余过滤器也包含or在内,也请使用括号将它们括起来,以确保您不会意外地将“中间咬合”的过滤器变为可选项。

SQL查询

select A.name_lf, A.company, B.name_fl, B.fav_food
from CONVENTION A
full outer join RESTAURANT B on A.ph = B.phone and A.em = B.email
where 
    (
    A.ph is null
    and A.em is null
    )
or
    (
    B.phone is null
    and B.email is null
    );
Enter fullscreen mode Exit fullscreen mode

查询输出

名称_lf 公司 名称_fl 最喜欢的食物
阿姆吉特·阿努什 苹果
博尔赫斯,贝尼塔 布瓦龙
凯茜·库姆斯 CVS
凯茜·库姆斯 胡萝卜
海伦·霍珀 鹰嘴豆泥

你成功了!感觉自己又聪明了多少?


更多资源

如果您喜欢这篇文章,您可能感兴趣的其他链接是:

文章来源:https://dev.to/katiekodes/every-sql-join-youll-ever-need-2hbd
PREV
如何通过 2020 年 AWS 认证云从业者考试
NEXT
你的问题很荒谬,但无论如何都要问