新聞中心
連接(Join)是將兩個(gè)或多個(gè)表、視圖或物化視圖的結(jié)合在一起的查詢。當(dāng)查詢的 ?FROM? 子句中出現(xiàn)多個(gè)表時(shí) OceanBase 數(shù)據(jù)庫會(huì)進(jìn)行連接查詢,查詢輸出列可以從 ?FROM? 子句任何表中選取。 如果多個(gè)表都有一個(gè)列名,那么您必須用表名限定查詢過程中對(duì)這些列的所有引用。數(shù)據(jù)庫中的連接類型一般包括 ?inner join?、?outer join?、?semi-join? 和 ?anti-join?。其中 ?Semi-join? 和 ?Anti-join? 都是通過子查詢改寫得到,OceanBase 本身并沒有表述 ?Anti-join? 和 ?Semi-join? 的語法。

創(chuàng)新互聯(lián)公司2013年開創(chuàng)至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站建設(shè)、網(wǎng)站制作網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元綦江做網(wǎng)站,已為上家服務(wù),為綦江各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18980820575
連接條件
連接條件是將多表結(jié)合在一起的規(guī)則,存在于從句或 ?WHERE? 子句中,用于比較來自不同的表兩列,多數(shù)連接至少包含一個(gè)連接條件。連接條件可以分為等值連接(比如 t1.a = t2.b)和非等值連接(t1.a < t2.b),相比于非等值連接條件, 等值連接條件允許數(shù)據(jù)庫使用高效的連接算法,比如 ?Hash Join? 和 ?Merge-Sort join?。
為了執(zhí)行連接,OceanBase 從不同表取行組合成對(duì),使用連接條件進(jìn)行匹配。 要執(zhí)行兩表以上的多表連接,OceanBase 首先根據(jù)比較它們的列的連接條件連接其中的兩個(gè)表,然后根據(jù)包含連接表和新表列的連接條件將結(jié)果連接到另一個(gè)表。優(yōu)化器根據(jù)連接條件、基表索引以及可用統(tǒng)計(jì)信息確定 OceanBase 連接順序。
?WHERE? 子句除了連接條件還可能含有其他條件,這些僅引用一個(gè)表的條件可以進(jìn)一步限制連接查詢返回的行數(shù)。
等值連接(EQUI-JOINS)
等值連接(Equijoins)是連接條件包含等式運(yùn)算符的連接。進(jìn)行等值連接時(shí)將特定列滿足等值條件的行進(jìn)行組合輸出。
自連接(SELF-JOIN)
自連接是表與其自身的連接。該表在 ?FROM? 子句中出現(xiàn)兩次,后跟表別名,這些別名限定聯(lián)接條件中的列名。執(zhí)行自連接時(shí)OceanBase數(shù)據(jù)庫將組合并返回滿足連接條件的行。
笛卡兒積(Cartesian Products)
如果連接查詢中的兩個(gè)表沒有連接條件,OceanBase 數(shù)據(jù)庫返回其笛卡爾乘積,使用第一個(gè)表的每一行與另一表每一個(gè)行進(jìn)行組合輸出。笛卡爾乘積總是生成許多行,很少有用。 例如,兩個(gè)都有 100 行的表的笛卡爾積有 10,000 行。除非您特別需要笛卡爾乘積,否則始終包括一個(gè)連接條件。 如果查詢連接了三個(gè)或多個(gè)表,并且沒有為特定對(duì)指定連接條件,則優(yōu)化器可以選擇避免生成中間笛卡爾乘積的連接順序。
內(nèi)連接(INNER JOIN)
內(nèi)連接(INNER JOIN)是數(shù)據(jù)庫中最基本的連接操作。內(nèi)連接基于連接條件將兩張表(如 A 和 B)的列組合在一起,產(chǎn)生新的結(jié)果表。查詢會(huì)將 A 表的每一行和 B 表的每一行進(jìn)行比較,并找出滿足連接條件的組合。當(dāng)連接條件被滿足,A 和 B 中匹配的行會(huì)按列組合(并排組合)成結(jié)果集中的一行。連接產(chǎn)生的結(jié)果集等于首先對(duì)兩張表做笛卡爾積,將 A 中的每一行和 B 中的每一行組合,然后返回滿足連接條件的記錄。
外連接(OUTER JOIN)
外連接(OUTER JOIN) 返回滿足連接條件的所有行,同時(shí)從一個(gè)表返回沒有使用的行,在另一個(gè)表相應(yīng)位置填充 ?NULL?。外連接可依據(jù)連接表保留左表、右表或全部表的行而進(jìn)一步分為左連接、右連接和全連接。其中左連接(LEFT [OUTER] JOIN)中左表行未在右表匹配到行時(shí),在右表自動(dòng)填充 ?NULL?。右連接(RIGHT [OUTER] JOIN)中右表行未在左表匹配到行時(shí),在左表自動(dòng)填充 ?NULL?。全連接(FULL [OUTER] JOIN)左表或者右表未在其它表匹配到行時(shí)均會(huì)填充 ?NULL?。
SEMI 連接(SEMI-JOIN)
當(dāng) A 表和 B 表進(jìn)行 ?LEFT? 或 ?RIGHT ANTI-JOIN? 的時(shí)候,它只返回 A 或 B 中所有能夠在 B 或 A 中找到匹配的行。?SEMI-JOIN? 只能通過子查詢展開得到。
ANTI 連接(ANTI-JOIN)
當(dāng) A 表和 B 表進(jìn)行 ?LEFT? 或 ?RIGHT ANTI-JOIN? 的時(shí)候,它只返回 A 或 B 中所有不能在 B 或 A 中找到匹配的行。類似于 ?SEMI-JOIN?,?ANTI-JOIN? 也只能通過子查詢展開得到。
示例
建立表 table_a 和表 table_b,并插入數(shù)據(jù)。執(zhí)行以下語句:
CREATE TABLE table_a(PK INT, name VARCHAR(25));
INSERT INTO table_a VALUES(1,'??怂?);
INSERT INTO table_a VALUES(2,'警察');
INSERT INTO table_a VALUES(3,'的士');
INSERT INTO table_a VALUES(4,'林肯');
INSERT INTO table_a VALUES(5,'亞利桑那州');
INSERT INTO table_a VALUES(6,'華盛頓');
INSERT INTO table_a VALUES(7,'戴爾');
INSERT INTO table_a VALUES(10,'朗訊');
CREATE TABLE table_b(PK INT, name VARCHAR(25));
INSERT INTO table_b VALUES(1,'??怂?);
INSERT INTO table_b VALUES(2,'警察');
INSERT INTO table_b VALUES(3,'的士');
INSERT INTO table_b VALUES(6,'華盛頓');
INSERT INTO table_b VALUES(7,'戴爾');
INSERT INTO table_b VALUES(8,'微軟');
INSERT INTO table_b VALUES(9,'蘋果');
INSERT INTO table_b VALUES(11,'蘇格蘭威士忌');自連接查詢(SELF-JOIN):
SELECT * FROM table_a ta, table_a tb WHERE ta.NAME = tb.NAME;查詢結(jié)果如下:
+------+-----------------+------+-----------------+
| PK | NAME | PK | NAME |
+------+-----------------+------+-----------------+
| 1 | ??怂? | 1 | ??怂? |
| 2 | 警察 | 2 | 警察 |
| 3 | 的士 | 3 | 的士 |
| 4 | 林肯 | 4 | 林肯 |
| 5 | 亞利桑那州 | 5 | 亞利桑那州 |
| 6 | 華盛頓 | 6 | 華盛頓 |
| 7 | 戴爾 | 7 | 戴爾 |
| 10 | 朗訊 | 10 | 朗訊 |
+------+-----------------+------+-----------------+內(nèi)連接(INNER JOIN)查詢:
SELECT A.PK AS A_PK, A.name AS A_Value, B.PK AS B_PK, B.name AS B_Value
FROM table_a A INNER JOIN table_b B ON A.PK = B.PK;查詢結(jié)果如下:
+------+-----------+------+-----------+
| A_PK | A_VALUE | B_PK | B_VALUE |
+------+-----------+------+-----------+
| 1 | 福克斯 | 1 | ??怂? |
| 2 | 警察 | 2 | 警察 |
| 3 | 的士 | 3 | 的士 |
| 6 | 華盛頓 | 6 | 華盛頓 |
| 7 | 戴爾 | 7 | 戴爾 |
+------+-----------+------+-----------+左連接查詢:
SELECT A.PK AS A_PK, A.name AS A_Value, B.PK AS B_PK, B.name AS B_Value
FROM table_a A LEFT JOIN table_b B ON A.PK = B.PK;查詢結(jié)果如下:
+------+-----------------+------+-----------+
| A_PK | A_VALUE | B_PK | B_VALUE |
+------+-----------------+------+-----------+
| 1 | ??怂? | 1 | ??怂? |
| 2 | 警察 | 2 | 警察 |
| 3 | 的士 | 3 | 的士 |
| 6 | 華盛頓 | 6 | 華盛頓 |
| 7 | 戴爾 | 7 | 戴爾 |
| 4 | 林肯 | NULL | NULL |
| 5 | 亞利桑那州 | NULL | NULL |
| 10 | 朗訊 | NULL | NULL |
+------+-----------------+------+-----------+右連接查詢:
obclient> SELECT A.PK AS A_PK, A.name AS A_Value, B.PK AS B_PK, B.name AS B_Value FROM table_a A RIGHT JOIN table_b B ON A.PK = B.PK;查詢結(jié)果如下:
+------+-----------+------+--------------------+
| A_PK | A_VALUE | B_PK | B_VALUE |
+------+-----------+------+--------------------+
| 1 | ??怂? | 1 | ??怂? |
| 2 | 警察 | 2 | 警察 |
| 3 | 的士 | 3 | 的士 |
| 6 | 華盛頓 | 6 | 華盛頓 |
| 7 | 戴爾 | 7 | 戴爾 |
| NULL | NULL | 8 | 微軟 |
| NULL | NULL | 9 | 蘋果 |
| NULL | NULL | 11 | 蘇格蘭威士忌 |
+------+-----------+------+--------------------+全連接查詢:
obclient> SELECT A.PK AS A_PK,A.name AS A_Value,B.PK AS B_PK,B.name AS B_Value FROM table_a A FULL JOIN table_b B ON A.PK = B.PK;查詢結(jié)果如下:
+------+-----------------+------+--------------------+
| A_PK | A_VALUE | B_PK | B_VALUE |
+------+-----------------+------+--------------------+
| 1 | 福克斯 | 1 | ??怂? |
| 2 | 警察 | 2 | 警察 |
| 3 | 的士 | 3 | 的士 |
| 6 | 華盛頓 | 6 | 華盛頓 |
| 7 | 戴爾 | 7 | 戴爾 |
| NULL | NULL | 8 | 微軟 |
| NULL | NULL | 9 | 蘋果 |
| NULL | NULL | 11 | 蘇格蘭威士忌 |
| 4 | 林肯 | NULL | NULL |
| 5 | 亞利桑那州 | NULL | NULL |
| 10 | 朗訊 | NULL | NULL |
+------+-----------------+------+--------------------+Semi 連接(semi-join):有依賴關(guān)系的子查詢被展開改寫成 SEMI-JOIN。
explain SELECT * FROM table_a t1 WHERE t1.PK IN (SELECT t2.PK FROM table_b t2 WHERE t2.NAME = t1.NAME);查詢結(jié)果如下:
+------------------------------------------------+
| Query Plan |
+------------------------------------------------+
=======================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
---------------------------------------
|0 |HASH SEMI JOIN| |8 |114 |
|1 | TABLE SCAN |T1 |8 |38 |
|2 | TABLE SCAN |T2 |8 |38 |
=======================================
Outputs & filters:
-------------------------------------
0 - output([T1.PK], [T1.NAME]), filter(nil),
equal_conds([T1.PK = T2.PK], [T2.NAME = T1.NAME]), other_conds(nil)
1 - output([T1.NAME], [T1.PK]), filter(nil),
access([T1.NAME], [T1.PK]), partitions(p0)
2 - output([T2.NAME], [T2.PK]), filter(nil),
access([T2.NAME], [T2.PK]), partitions(p0)
+------------------------------------------------+Anti 連接(anti-join):有依賴關(guān)系的子查詢被改寫成 ?Anti-join?。
EXPLAIN SELECT * FROM table_a t1 WHERE t1.PK NOT IN (SELECT t2.PK
FROM table_b t2 WHERE t2.name = t1.name);查詢結(jié)果如下:
+------------------------------------------------+
| Query Plan |
+------------------------------------------------+
=======================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
---------------------------------------
|0 |HASH ANTI JOIN| |0 |112 |
|1 | TABLE SCAN |T1 |8 |38 |
|2 | TABLE SCAN |T2 |8 |38 |
=======================================
Outputs & filters:
-------------------------------------
0 - output([T1.PK], [T1.NAME]), filter(nil),
equal_conds([T2.NAME = T1.NAME]), other_conds([(T_OP_OR, T1.PK = T2.PK,
(T_OP_IS, T1.PK, NULL, 0), (T_OP_IS, T2.PK, NULL, 0))])
1 - output([T1.NAME], [T1.PK]), filter(nil),
access([T1.NAME], [T1.PK]), partitions(p0)
2 - output([T2.NAME], [T2.PK]), filter(nil),
access([T2.NAME], [T2.PK]), partitions(p0)
+---------------------------------------------------------+ 標(biāo)題名稱:創(chuàng)新互聯(lián)OceanBase教程:OceanBase連接
文章出自:http://m.fisionsoft.com.cn/article/dpcehph.html


咨詢
建站咨詢
