閱讀本文章,你將了解 SQL 有趣的一面,即連接表并創(chuàng)建 UNION。
如果您在本系列到目前為止對 SQL 感到有點距離或疏遠,請不要害怕:我們即將發(fā)現(xiàn)關系數(shù)據(jù)庫如此...關系的魔力。關掉燈光,播放您最喜歡的 Marvin Gaye 歌曲;我們即將在另一個層面上建立聯(lián)系。
我發(fā)現(xiàn)現(xiàn)有的解釋數(shù)據(jù)庫關系(特別是 JOIN)的嘗試在說明這些概念方面完全失敗了。我們都習慣看到的維恩圖對于從未見過 JOIN 發(fā)生的人來說毫無意義,即使如此,它們真的描述了正在發(fā)生的事情嗎?我很樂意將一些快速動畫放在一起作為替代方案,但很可能我會像我們其他人一樣選擇平庸的動畫。
關系數(shù)據(jù)庫的實際應用
盡管到目前為止我們已經(jīng)介紹了 SQL,但我們?nèi)匀粵]有進行“討論”。天啊,不,不是那個談話;我的意思是必須舉例說明兩張桌子如何與另一張桌子相關聯(lián)。這個談話沒那么尷尬,但它絕對不會讓你為生活中更美好的事情做好準備。開玩笑,數(shù)據(jù)是生活中美好的一部分?;蛘咧辽偎谖业纳砩?。我們不要在這個問題上停留太久。
讓我們看一下用于說明數(shù)據(jù)關系的最常見場景:客戶與訂單的困境。假設我們決定開設一個有機純素古酮羽衣甘藍 Voltron 5000健康食品市場來迎合高端客戶:自命不凡的富有混蛋。碰巧的是,“富有的混蛋”市場非常容易接受客戶關系中的最佳實踐,因此我們啟動了 CRM 來跟蹤我們的最佳客戶。這種記錄保存可以幫助我們假裝記住客戶的姓名和個性:
客戶表
id | first_name | last_name | gender | state | phone | |
---|---|---|---|---|---|---|
653466635 | Timothea | Crat | tcrat0@bandcamp.com | Female | Washington | 206-220-3752 |
418540868 | Kettie | Fuggle | kfuggle1@cafepress.com | Female | California | 661-793-1372 |
857532654 | Boonie | Sommerland | bsommerland2@soundcloud.com | Male | North Carolina | 919-299-0715 |
563295938-4 | Red | Seldon | rseldon3@addthis.com | Male | Indiana | 765-880-7420 |
024844147 | Marika | Gallatly | mgallatly4@loc.gov | Female | New York | 718-126-1462 |
900992907 | Sharlene | McMaster | smcmaster5@gmpg.org | Female | Nevada | 775-376-0931 |
329211747-X | Grover | Okey | gokey6@weather.com | Male | Texas | 915-913-0625 |
656608031 | Farly | Pluck | fpluck7@buzzfeed.com | Male | Texas | 432-670-8809 |
906380018 | Sumner | Pickerell | spickerellb@bloglovin.com | Male | Colorado | 719-239-5042 |
另一方面,我們需要跟蹤庫存和已售商品。既然我們已經(jīng)在刷信用卡并獲取所有這些個人客戶數(shù)據(jù),為什么不將購買與忠實客戶關聯(lián)起來呢?因此,我們有一個交易列表,看起來像這樣:
訂單表
item_id | customer_id | item_purchased | first_name | last_name | amount | date_purchased |
---|---|---|---|---|---|---|
82565290-530d-4272-9c8b-38dc0bc7426a | 653466635 | Creme De Menthe Green | Timothea | Crat | $8.57 | 5/13/18 |
9cfa5f5c-6a9c-4400-8f0f-f8262a787cd0 | 653466635 | Veal Inside - Provimi | Timothea | Crat | $5.77 | 3/3/18 |
5dea0cce-c6be-4f35-91f6-0c6a1a8b8f11 | 656608031 | Arizona - Plum Green Tea | Grover | Okey | $1.72 | 9/6/18 |
b4813421-12e8-479b-a3b6-3d1c4c539625 | 656608031 | Beer - Fruli | Grover | Okey | $4.05 | 10/1/18 |
4e7c8548-340f-4e89-a7f1-95173dcc6e53 | 656608031 | Boogies | Grover | Okey | $1.97 | 12/17/18 |
65261e94-494d-48cc-8d5a-642ae6921600 | 656608031 | Cup - 3.5oz; Foam | Grover | Okey | $1.84 | 11/28/18 |
1bfdca0f-d54a-4845-bbf5-982813ab4a65 | 656608031 | Arizona - Green Tea | Grover | Gauford | $0.22 | 5/23/18 |
d20d7add-bad4-4559-8896-d4f6d05aa3dd | 906380018 | Lemonade - Strawberry; 591 Ml | Sumner | Tortoishell | $7.98 | 10/11/18 |
12134510-bc6c-4bd7-b733-b549a61edaa3 | 906380018 | Pasta - Cappellini; Dry | Sumner | Wash | $0.31 | 11/13/18 |
80f1957c-df4d-40dc-b9c4-2c3939dd0865 | 906380018 | Remy Red Berry Infusion | Sumner | Pisculli | $1.25 | 12/31/18 |
a75f7593-3312-43e4-a604-43405f02efdd | 906380018 | Veal - Slab Bacon | Sumner | Janaszewski | $9.80 | 3/9/18 |
c6ef1f55-f35d-4618-8de7-36f59ea6653a | 906380018-5 | Beans - Black Bean; Dry | Sumner | Piegrome | $1.36 | 12/11/18 |
c5b87ee3-da94-41b1-973a-ef544a3ffb6f | 906380018 | Calypso - Strawberry Lemonade | Sumner | Piegrome | $7.71 | 2/21/19 |
e383c58b-d8da-40ac-afd6-7ee629dc95c6 | 656608031 | Basil - Primerba; Paste | Mohammed | Reed | $2.77 | 10/21/18 |
d88ccd5b-0acb-4144-aceb-c4b4b46d3b17 | 656608031 | Cheese - Fontina | Mohammed | Reed | $4.24 | 7/14/18 |
659df773-719c-447e-a1a9-4577dc9c6885 | 656608031 | Cotton Wet Mop 16 Oz | Jock | Skittles | $8.44 | 1/24/19 |
ff52e91e-4a49-4a52-b9a5-ddc0b9316429 | 656608031 | Pastry - Trippleberry Muffin - Mini | Jock | Skittles | $9.77 | 11/17/18 |
86f8ad6a-c04c-4714-8f39-01c28dcbb3cb | 656608031 | Bread - Olive | Jock | Skittles | $4.51 | 1/10/19 |
e7a66b71-86ff-4700-ac57-71291e6997b0 | 656608031 | Wine - White; Riesling; Semi - Dry | Farly | Pluck | $4.23 | 4/15/18 |
c448db87-1246-494a-bae4-dceb8ee8a7ae | 656608031 | Melon - Honey Dew | Farly | Pluck | $1.00 | 9/10/18 |
725c171a-452d-45ef-9f23-73ef20109b90 | 656608031 | Sugar - Invert | Farly | Pluck | $9.04 | 3/24/18 |
849f9140-1469-4e23-a1de-83533af5fb88 | 656608031 | Yokaline | Farly | Pluck | $3.21 | 12/31/18 |
2ea79a6b-bfec-4a08-9457-04128f3b37a9 | 656608031 | Cake - Bande Of Fruit | Farly | Pluck | $1.57 | 5/20/18 |
當然,顧客會購買不止一件商品;他們買了很多。尤其是底部的那個Farly Pluck家伙——這是一個非常不幸的自動生成的名字。
作為獨立的表,客戶表和訂單表各自至少有一個簡單的用途。客戶表幫助我們進行消費者人口統(tǒng)計分析,而訂單表則確保我們賺錢并且不會被搶。雖然這兩個功能很重要,但都不是特別具有革命性:自 70 年代以來,基本的記錄保存水平一直是幾乎所有企業(yè)的核心。
組合數(shù)據(jù)的能力使我們能夠獲得更重要的見解。我們可以獎勵忠實的客戶,根據(jù)個人的喜好滿足他們的需求,甚至可能將 Pluck 先生過去 4 個月每周二和周四所在地點和時間的個人數(shù)據(jù)出售給出價最高的數(shù)據(jù)經(jīng)紀人(提示:他在我們店里)。
感謝關系數(shù)據(jù)庫,我們既不限于單個整體表,也不被我們前面設置的表的約束所束縛。關聯(lián)數(shù)據(jù)很簡單,只要我們有一種方法可以通過 來關聯(lián)它。下面是將訂單表中的外鍵與客戶表中的主鍵進行匹配的可視化:
訂單的外鍵引用客戶的 ID
上面說明了我們已經(jīng)了解過的內(nèi)容:外鍵關聯(lián)。主鍵和外鍵對于描述表之間的關系以及執(zhí)行 SQL 連接至關重要。話不多說,讓我們加入一些數(shù)據(jù)。
連接數(shù)據(jù)集
“連接”多組數(shù)據(jù)就是將多個表合并為一個。
這種合并的方式取決于我們使用的四種連接表方法中的哪一種:內(nèi)連接、右連接、左連接和外連接(左連接和右連接有點相同,但無論如何)。無論join的類型如何,所有 join 都具有以下共同點:
行比較:我們查找表 A中的列值與表 B中的列值匹配的行。
列合并:任何聯(lián)接的目的都是得到一個包含兩個表中的列的表。
左連接和右連接
LEFT和RIGHT聯(lián)接涵蓋了無數(shù)的用例。只要發(fā)揮一點創(chuàng)造力,左/右連接就可以幫助解決我們可能沒有預料到的問題。術語“左”和“右”是指從左到右閱讀時我們想要加入的表格。當通過 連接表時LEFT JOIN,查詢中的第一個表將是“左”表?;蛘?,aRIGHT JOIN指最后一個表。
當我們說“要加入的表”時,我們指定哪個表的鍵值將成為我們合并的“權限”。在 a 中LEFT MERGE,表 A中的所有記錄都將在合并后保留下來:
對于在Table B中具有匹配項的行,這些行將被“擴展”以包含Table B中的數(shù)據(jù)。這意味著從表 B添加到表 A 的新列將包含已進行關聯(lián)的所有行的數(shù)據(jù)。
對于表 A中存在但在表 B中不匹配的行,這些行不受影響:它們將包含與連接之前相同的數(shù)據(jù),新列中的值留空。
表B中存在但表A中不存在的鍵將被丟棄。這些連接的目的是豐富主表的數(shù)據(jù)。
下面是我用來為“項目”頁面上的看板模塊提供支持的實際左連接示例。左表是 JIRA 問題表,右表是基于問題的自定義的集合,例如問題類型的自定義圖標和顏色??纯催@些數(shù)據(jù)是如何關聯(lián)的,以及是什么使它進入最終的表:
左表上的鍵決定哪些行保留或消失。
查詢的結(jié)構(gòu)LEFT JOIN如下所示:
SELECT table_1.*, table_2.* FROM t1 LEFT JOIN t2 ON t1.column_name = t2.column_name;
這是一個具有實際值的示例:
SELECT first_name, last_name, order_date, order_amount FROM customers c LEFT JOIN orders o ON c.customer_id = o.customer_id;
將此與RIGHT JOIN 進行比較:
SELECT first_name, last_name, order_date, order_amount FROM customers c RIGHT JOIN orders o ON c.customer_id = o.customer_id;
內(nèi)連接(或交叉連接)
內(nèi)連接是連接數(shù)據(jù)集最保守的方法。LEFT與或連接不同RIGHT,內(nèi)部連接中沒有權威表:只有在所有表中包含匹配項的行才能在連接中幸存。所有其他行將被忽略:
SELECT table_1.column_name(s), table_2.column_name(s), FROM table1 INNER JOIN table2 ON table1.column_name = table2.column_name;
由于內(nèi)部聯(lián)接僅作用于所有受影響表中匹配的行,因此內(nèi)部聯(lián)接通常包含最“完整”的數(shù)據(jù)集(滿足值的最大列數(shù)),但包含最少的行數(shù)。
外部連接
外連接實際上有幾種不同的風格。一般來說,外連接可以最大限度地提高執(zhí)行連接后存活的數(shù)據(jù)量。
左(或右)外連接
乍一看,您可能會看到左/右外連接的結(jié)果,并誤認為它們與純左/右連接對應的結(jié)果完全相同。嗯,其實你根本就不會錯!是的,我在撒謊:連接類型之間本質(zhì)上沒有區(qū)別(因此我們提及它們的時間毫無價值)。
全外連接
在完全外連接中,所有列和行都將連接到結(jié)果輸出中,無論行是否與我們指定的鍵匹配。您可能會問,為什么我們要指定一個密鑰?鍵上的匹配行仍然會合并與所有涉及的表相似的行(如果在合并過程中確實沒有具有共同點的行,您應該問自己為什么首先要合并兩個不相關的數(shù)據(jù)集)。
結(jié)果有點亂。我將在這里借用Pandas文檔可以查看:(pandas.pydata.org/pandas-docs/stable/user_guide/merging.html)
雖然 B 列似乎保持完整,但看看它周圍發(fā)生的情況:由于連接而生成了標記為A_x和A_y的列。外連接創(chuàng)建了一個表,其中存在 B 列中鍵值的所有可能組合。因此,新表中的行數(shù)實際上是表 A 的 長度*表 B 的長度。
我個人很少使用外連接,但這只是我的情況。
SELECT column_name(s) FROM table1 FULL OUTER JOIN table2 ON table1.column_name = table2.column_name;
場景:從多個 JOIN 創(chuàng)建新表
到目前為止,我們只查看了同時連接兩個表的示例。事實上,我們可以一次合并任意數(shù)量的表!回到 JIRA 示例,下面是我用來創(chuàng)建支持自定義看板的最終表的實際查詢:
CREATE TABLE jira AS SELECT jira_issues.*, jira_issuetypes.issuetype_url, jira_issuetypes.issuetype_color, jira_epiccolors.epic_color FROM jira_issues LEFT JOIN jira_issuetypes ON jira_issues.issuetype = jira_issuetypes.issuetype LEFT JOIN jira_epiccolors ON jira_issues.epic_name = jira_epiccolors.epic_name;
如果您使用 PostgreSQL,視圖是保存聯(lián)接結(jié)果而無需添加其他表的好方法。不要使用CREATE TABLE,而是嘗試使用CREATE VIEW:
CREATE VIEW jira AS SELECT jira_issues.*, jira_issuetypes.issuetype_url, jira_issuetypes.issuetype_color, jira_epiccolors.epic_color FROM jira_issues LEFT JOIN jira_issuetypes ON jira_issues.issuetype = jira_issuetypes.issuetype LEFT JOIN jira_epiccolors ON jira_issues.epic_name = jira_epiccolors.epic_name;
工會和全體工會
考慮JOINs 的一個好方法是水平擴展我們的數(shù)據(jù)集。UNION那么,A是一種垂直組合數(shù)據(jù)的方式。聯(lián)合 將具有相同結(jié)構(gòu)的數(shù)據(jù)集組合起來:它們只是創(chuàng)建一個包含兩個表中的行的表。UNION運算符可以組合兩個或多個 SELECT 語句的結(jié)果集,只要:
UNION 中的每個 SELECT 語句必須具有相同的列數(shù)。
這些列還必須具有相似的數(shù)據(jù)類型。
每個 SELECT 語句中的列也必須具有相同的順序。
聯(lián)盟
SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2;
聯(lián)合(與 WHERE)
我們還可以通過where語句向聯(lián)合添加邏輯:
SELECT City, Country FROM Customers WHERE Country='Germany' UNION SELECT City, Country FROM Suppliers WHERE Country='Germany' ORDER BY City;
聯(lián)合所有
UNION一個有趣的區(qū)別是vs的存在UNION ALL。兩者之中,UNION是更“智能”的操作:如果兩個 SELECT 中都存在相同的行queries,則 aUNION會知道只給我們一行以避免重復。另一方面,UNION ALL 確實返回重復項:這會導致更快的查詢,并且對于那些想知道這兩個SELECT語句中的內(nèi)容的人可能很有用:
SELECT column_name(s) FROM table1 UNION ALL SELECT column_name(s) FROM table2;
UNION ALL(與 WHERE)
就像 一樣,我們可以通過whereUNION語句添加邏輯來聯(lián)合所有:
SELECT City, Country FROM Customers WHERE Country='Germany' UNION ALL SELECT City, Country FROM Suppliers WHERE Country='Germany' ORDER BY City;
更多 SQL 未來
我希望可視化JOIN和UNION 的工作方式能夠幫助減少 SQL 新手的摩擦。我發(fā)現(xiàn)很難相信人類能夠在沒有親眼目睹這些概念發(fā)生的情況下完全掌握這些概念,這就引出了一個問題:為什么有人會在不知道其好處的情況下探索解釋得如此糟糕的東西?
如果您發(fā)現(xiàn)這些指南有用,歡迎向我喊話,讓它們繼續(xù)出現(xiàn)。我們的系列中還有更多 SQL:請繼續(xù)關注我們探索聚合值等內(nèi)容!文章來源:http://www.zghlxwxcb.cn/article/576.html
文章來源地址http://www.zghlxwxcb.cn/article/576.html
到此這篇關于從零開始學習SQL數(shù)據(jù)庫操作:建立關系和組合數(shù)據(jù)集的文章就介紹到這了,更多相關內(nèi)容可以在右上角搜索或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!