Oracle中的连接查询讲解

最近在写需求的时候遇上一个连接查询的问题,趁此机会讲解下Oracle中的连接查询

Oracle中主要的连接操作

连接类型 说明
INNER JOIN 内联接,结果为两个联接表中的匹配行的联接
LEFT JOIN 左联接:结果包括左表(出现在JOIN子句最左边)中的所有行,不包括右表中的不匹配行
RIGHT JOIN 右联接:结果包括右表(出现在JOIN子句最右边)中的所有行,不包括左表中的不匹配行
FULL JOIN 完全联接:结果包括所有联接中的所有行,不论他们是否匹配
CROSS JOIN 交叉联接:结果包括两个联接表中的所有可能的行组合,交叉连接返回的是两个表的笛卡儿积(Oracle不支持)
NATURAL JOIN 自然连接时在两张表中寻找那些数据类型 和列名都相等的字段,然后自动地将他们连接起来

不同的联接类型决定了如何处理联接条件中不匹配的元素,接下来就以左联接为例来描述我所遇到的问题。

示例所需SQL脚本

此处直接选用了我在项目中的数据脚本,有需要的可以直接download下来操作

  1. https://github.com/LeonardoEzio/Oracle-Join/blob/master/SQL/FORE_TICKET_CANCEL.sql
  2. https://github.com/LeonardoEzio/Oracle-Join/blob/master/SQL/FORE_TICKETCANCEL_SEGMENT.sql

在Idea 中执行SQL脚本

  1. 首先将所下载的sql脚本放入工程目录中,如下图:


    SQL脚本所在工程目录结构.png
  2. 在打开的SQL文件中按 Ctrl + Shift + F10 在弹出的页面中选择在哪个库执行即可(本列使用的是oracle数据库)


    数据库选择.png

本人所遇问题描述

  • 问题1:

执行SQL片段1

SELECT
  FTC.FTC_TICKETCANCEL_NO,
  FTC.FTC_TA_NO AS TA_NO,
  FTS.FTCS_ARR_DATE AS ARR_DATE,
  FTS.FTCS_DEP_DATE AS DEP_DATE,
  FTC.FTC_CREATEDATATIME AS createTm
FROM FORE_TICKET_CANCEL FTC
  LEFT  JOIN  FORE_TICKETCANCEL_SEGMENT FTS
    ON FTC.FTC_TICKETCANCEL_NO =  FTS.FTCS_TICKETCANCEL_NO
    AND FTC.FTC_TA_NO='2019021900003';--查询结果 3657条记录

SELECT FTC.* FROM FORE_TICKET_CANCEL FTC;-- 主表(左表FTC)记录总数 3657

SELECT
  FTC.FTC_TICKETCANCEL_NO,
  FTC.FTC_TA_NO AS TA_NO,
  FTS.FTCS_ARR_DATE AS ARR_DATE,
  FTS.FTCS_DEP_DATE AS DEP_DATE,
  FTC.FTC_CREATEDATATIME as createTm
FROM FORE_TICKETCANCEL_SEGMENT FTS
  LEFT JOIN FORE_TICKET_CANCEL FTC
    ON FTS.FTCS_TICKETCANCEL_NO = FTC.FTC_TICKETCANCEL_NO
    AND FTC.FTC_TA_NO='2019021900003';--查询结果 4669条记录

SELECT FTS.* FROM FORE_TICKETCANCEL_SEGMENT FTS;-- 主表(左表FTS)记录总数 4669

执行SQL片段2

SELECT
  FTC.FTC_TICKETCANCEL_NO,
  FTC.FTC_TA_NO AS TA_NO,
  FTS.FTCS_ARR_DATE AS ARR_DATE,
  FTS.FTCS_DEP_DATE AS DEP_DATE,
  FTC.FTC_CREATEDATATIME as createTm
FROM FORE_TICKET_CANCEL FTC
  LEFT  JOIN  FORE_TICKETCANCEL_SEGMENT FTS
  ON FTC.FTC_TICKETCANCEL_NO =  FTS.FTCS_TICKETCANCEL_NO;--查询结果 4669条记录

SELECT FTC.* FROM FORE_TICKET_CANCEL FTC;-- 主表(左表FTC)记录总数 3657

SELECT
  FTC.FTC_TICKETCANCEL_NO,
  FTC.FTC_TA_NO AS TA_NO,
  FTS.FTCS_ARR_DATE AS ARR_DATE,
  FTS.FTCS_DEP_DATE AS DEP_DATE,
  FTC.FTC_CREATEDATATIME as createTm
FROM FORE_TICKETCANCEL_SEGMENT FTS
  LEFT JOIN FORE_TICKET_CANCEL FTC
  ON FTS.FTCS_TICKETCANCEL_NO = FTC.FTC_TICKETCANCEL_NO;--查询结果 4669条记录

SELECT FTS.* FROM FORE_TICKETCANCEL_SEGMENT FTS;-- 主表(左表FTS)记录总数 4669

执行SQL片段1的时候,所产生的结果大家可能没什么异议,左连接查询以主表数据为主,所以连接查询的结果与主表记录条数一致容易理解,然后当我们去掉SQL片段1的AND条件后,发现SQL片段2中的第一段SQL执行结果与主表中的记录条数不一致。

根据如上对左连接的定义左联接查询出的结果包括左表(出现在JOIN子句最左边)中的所有行,不包括右表中的不匹配行。SQL片段2中的第一段SQL查询出的结果与右表中的总记录条数一致,说明了右表中的数据全部匹配上了。为了证实这个结论,我们只需将右边中的数据修改一下,使其中一条数据与左表关联不上,那么最后的查询结果应该是比4669少一条的。

首先,我们通过如下图所示的SQL查询出在右表中出现多次的FTCS_TICKETCANCEL_NO(因为联结是基于这个字段)。

SQL与查询结果.png

第二步,选取其中一条结果为条件去查询右表(FTS)中记录,并修改其中一条记录的FTCS_TICKETCANCEL_NO字段值,使其与左表关联不上。

修改前.png

修改后.png

修改后的值我们要记住,因为要之后要还原进行后续的操作。然后再执行SQL片段2中的第一条SQL如果查询出的结果为4668条的话说明我们的猜测成立。

查询结果.png
  • 问题2:

接着我尝试修改了下如下SQL片段3中AND后的FTC_TA_NO参数值,又发现不一样的结果。在进行以下操作之前记得恢复问题1中的数据修改。

SQL片段3

SELECT
  FTC.FTC_TICKETCANCEL_NO,
  FTC.FTC_TA_NO AS TA_NO,
  FTS.FTCS_ARR_DATE AS ARR_DATE,
  FTS.FTCS_DEP_DATE AS DEP_DATE,
  FTC.FTC_CREATEDATATIME as createTm
FROM FORE_TICKET_CANCEL FTC
  LEFT  JOIN  FORE_TICKETCANCEL_SEGMENT FTS
    ON FTC.FTC_TICKETCANCEL_NO =  FTS.FTCS_TICKETCANCEL_NO
    AND FTC.FTC_TA_NO='2019021900003';--查询结果 3657条记录

SELECT FTC.* FROM FORE_TICKET_CANCEL FTC;-- 主表(左表FTC)记录总数 3657

SQL片段4

SELECT
  FTC.FTC_TICKETCANCEL_NO,
  FTC.FTC_TA_NO AS TA_NO,
  FTS.FTCS_ARR_DATE AS ARR_DATE,
  FTS.FTCS_DEP_DATE AS DEP_DATE,
  FTC.FTC_CREATEDATATIME as createTm
FROM FORE_TICKET_CANCEL FTC
  LEFT  JOIN  FORE_TICKETCANCEL_SEGMENT FTS
    ON FTC.FTC_TICKETCANCEL_NO =  FTS.FTCS_TICKETCANCEL_NO
    AND FTC.FTC_TA_NO='2019021900004';--查询结果 3660条记录

SELECT FTC.* FROM FORE_TICKET_CANCEL FTC;-- 主表(左表FTC)记录总数 3657

SQL片段5

SELECT
  FTC.FTC_TICKETCANCEL_NO,
  FTC.FTC_TA_NO AS TA_NO,
  FTS.FTCS_ARR_DATE AS ARR_DATE,
  FTS.FTCS_DEP_DATE AS DEP_DATE,
  FTC.FTC_CREATEDATATIME as createTm
FROM FORE_TICKET_CANCEL FTC
  LEFT  JOIN  FORE_TICKETCANCEL_SEGMENT FTS
    ON FTC.FTC_TICKETCANCEL_NO =  FTS.FTCS_TICKETCANCEL_NO
    AND FTC.FTC_TA_NO='2019021900005';--查询结果 3658条记录

SELECT FTC.* FROM FORE_TICKET_CANCEL FTC;-- 主表(左表FTC)记录总数 3657

解释之前我们再重申以下左联接查询所产生的结果集 :包括左表(出现在JOIN子句最左边)中的所有行,加上右表中的匹配行。

到这里我们应该明白了FORE_TICKET_CANCEL表中的数据与FORE_TICKETCANCEL_SEGMENT中的数据是 1 : N的关系。

首先,我们来看SQL片段3中。SQL再执行查询的时候会根据FTC.FTC_TA_NO='2019021900003' 时 所对应的FTC.FTC_TICKETCANCEL_NO 在右表(FTS)中的记录条数来生成查询结果。


image1.png

接下来以image1的查询结果,为条件去查询右边(FTS)中符号条件的记录条数。


image2.png

最后可以得出以下结论,SQL片段三的最终结果 = 左表的记录条数 + (image1 与 image2 记录条数的差)

  • SQL片段4论证:
image1.png
image2.png

所以执行SQL片段4的所得的记录条数 = 左表(FTC)总记录数 + (image2记录条数 - image1记录条数)= 3657 + (4-1)= 3660

  • SQL片段5论证:
    image1.png
image2.png

所以执行SQL片段5所得的记录条数 = 左表(FTC)总记录数 + (image2记录条数 - image1记录条数)= 3657 + (2-1)= 3658


以上就是本人对Oracle中左联结查询所做的讲解,如示例中有错误的地方,请在评论中指正!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容