在关系型数据库中,表之间通常以某种方式相互关联,允许它们的信息在整个数据库中仅写入一次。然后,当你需要分析数据时,你需要组合来自这些相关表的信息。
要在 SQL 中执行此操作,您可以使用JOIN
语句。该LEFT JOIN
语句是可用的各种JOIN语句之一。当您使用它连接两个表时,它会保留第一个表(左表)的所有行,即使第二个表上没有对应的匹配项。
您可以JOIN
在SELECT
查询中使用连接两个表table_1
和table_2
,如下所示:
SELECT columns
FROM table_1
LEFT OUTER JOIN table_2
ON relation;
SELECT columns
FROM table_1
LEFT JOIN table_2
ON relation;
首先你写下哪些列将出现在连接表中。你可以通过在列名前加上表名来指定该列属于哪个表。如果某些列的名称(如table_1.column_1
和table_2.column_1
)与SELECT <columns>
.
然后你可以将第一个表的名称写为FROM table_1
.
之后,你再将第二个表的名称写为LEFT OUTER JOIN table_2
or LEFT JOIN table_2
(省略OUTER
关键字)。
最后,你要编写用于匹配行的关系,例如ON table_1.column_A = table_2.column_B
. 通常关系是通过 id 来的,但它可以是任何列。
SQL LEFT JOIN 示例
假设你有一个书籍数据库,其中有两个表,一个是书籍,另一个是作者。为避免重复每本书的所有作者信息,该信息位于其自己的表中,并且书籍只有该author_name
列。
BOOK_ID | TITLE | AUTHOR_NAME | PUBL_YEAR |
---|---|---|---|
1 | Uno, nessuno e centomila | 路易吉·皮兰德罗 | 1926 |
2 | Il visconte dimezzato | 伊塔洛·卡尔维诺 | 1952 |
3 | Le tigri di Mompracem | 埃米利奥·萨尔加里 | 1900 |
4 | Il giorno della civetta | 莱昂纳多·夏夏 | 1961 |
5 | A ciascuno il suo | 莱昂纳多·夏夏 | 1966 |
6 | Il fu Mattia Pascial | 路易吉·皮兰德罗 | 1904 |
7 | I Malavoglia | 乔瓦尼·维尔加 | 1881 |
AUTHOR_ID | NAME | YEAR_OF_BIRTH | PLACE_OF_BIRTH | TRVIA |
---|---|---|---|---|
1 | 路易吉·皮兰德罗 | 1867 | 阿格里真托 | 1934年诺贝尔文学奖 |
2 | 乔瓦尼·维尔加 | 1840 | 维齐尼 | 1920年至1922年任意大利王国参议员 |
3 | 伊塔洛·斯韦沃 | 1861 | 的里雅斯特 | 真名是Aron Hector Schmitz |
4 | 切萨雷·帕韦塞 | 1908 | 圣斯特凡诺贝尔博 | null |
5 | 朱塞佩·托马西·迪·兰佩杜萨 | 1896 | 巴勒莫 | 1934年至1957年任兰佩杜萨王子 |
我们可以根据作者的姓名连接这两个表。使用该books
表作为左表,你可以编写以下代码将它们连接起来:
SELECT books.title AS book_title, books.publ_year, books.author_name, authors.year_of_birth, authors.place_of_birth
FROM books
LEFT JOIN authors
ON books.author_name = authors.name
;
让我们分解一下。
在第一行中,你可以选择要在最终表格中显示的列。它也是决定某些列在结果表中是否具有不同名称的地方,使用AS
like with books.title AS book_title
。
第二行 ,FROM books
表示要考虑的第一个表,也称为左表。
然后第三行,LEFT JOIN authors
,说明要考虑的其他表。
ON books.author_name = authors.name
说使用行books.author_name
和匹配表authors.name
。
在此查询之后,您将获得如下表,其中未从作者表中获取信息的行仅显示NULL
.
BOOK_NAME | PUBL_YEAR | AUTHOR_NAME | YEAR_OF_BIRTH | PLACE_OF_YEAR |
---|---|---|---|---|
Uno, nessuno e centomila | 1926 | 路易吉·皮兰德罗 | 1867 | 阿格里真托 |
Il visconte dimezzato | 1952 | 伊塔洛·卡尔维诺 | null | null |
Le tigri di Mompracem | 1900 | 埃米利奥·萨尔加里 | null | null |
Il giorno della civetta | 1961 | 莱昂纳多·夏夏 | null | null |
A ciascuno il suo | 1966 | 莱昂纳多·夏夏 | null | null |
伊夫·马蒂亚·帕斯卡 | 1904 | 路易吉·皮兰德罗 | 1867 | 阿格里真托 |
我马拉沃利亚 | 1881 | 乔瓦尼·维尔加 | 1840 | 维齐尼 |
请注意,不在books
表中的作者不在此连接表中。这是因为,正如我之前所说,只保留左表(在本例中books
)中不相关的行,而不是右/第二个表中的行。
更复杂的 LEFT JOIN 示例
让我们看看另一种可以JOIN与其他 SQL 功能一起使用来进行数据分析的方法。
您可能想查看数据库中存在每位作者的图书数量。您可以使用以下查询来执行此操作:
SELECT authors.name AS author_name,
SUM(
CASE
WHEN books.title LIKE '%'
THEN 1
ELSE 0
END
) as number_of_books
FROM authors
LEFT JOIN books
ON books.author_name = authors.name
GROUP BY authors.name
ORDER BY number_of_books DESC
;
代码分解
第 1 行:SELECT
在结果表中列出所需的列。
第 2 行:SUM
是与 GROUP BY 结合使用的聚合函数。然后将组合在一起的行的值相加。
第 3-7 行:您使用CASE 语句
根据条件获得不同的结果。在这种情况下,如果一行包含书名,则计为 1,否则计为 0。这里我们LIKE
用来检查单元格是否包含任何字符。
第 8 行:这给出了number_of_books
为 SUM 创建的列的名称。
第 9 行:本例中的左/第一个表是authors
。
第 10 行:本例中右侧/第二个表是books
。
第 11 行:这将使用作者姓名连接两个表。
第 12 行:行按作者姓名分组- 该列中具有相同值的所有行将由一行表示。
第 13 行:我们使用order by使用书籍数量降序排列。
该查询将为您提供下表。请注意,在此处只能看到authors
表中的作者。books
表中提到的没有authors
表中条目的作者在此不存在。这是books
表中不相关的行没有保留这一事实的结果。
authors
表更新为包括books
表中提到的所有作者,如下所示:AUTHOR_NAME | NUMBER_OF_BOOKS |
---|---|
路易吉·皮兰德罗 | 2 |
乔瓦尼·维尔加 | 1 |
切萨雷·帕韦塞 | 0 |
朱塞佩·托马西·迪·兰佩杜萨 | 0 |
伊塔洛·斯韦沃 | 0 |
AUTHOR_ID | NAME | YEAR_OF_BIRTH | PLACE_OF_BIRTH | TRIVA |
---|---|---|---|---|
1 | 路易吉·皮兰德罗 | 1867 | 阿格里真托 | 1934年诺贝尔文学奖 |
2 | 乔瓦尼·维尔加 | 1840 | 维齐尼 | 1920年至1922年任意大利王国参议员 |
3 | 伊塔洛·斯韦沃 | 1861 | 的里雅斯特 | 真名是Aron Hector Schmitz |
4 | 切萨雷·帕韦塞 | 1908 | 圣斯特凡诺贝尔博 | nulll |
5 | 朱塞佩·托马西·迪·兰佩杜萨 | 1896 | 巴勒莫 | 1934年至1957年任兰佩杜萨王子 |
6 | 伊塔洛·卡尔维诺 | 1923 | 圣地亚哥·德·拉斯维加斯 | nulll |
7 | 埃米利奥·萨尔加里 | 1862 | 维罗纳 | nulll |
8 | 莱昂纳多·夏夏 | 1921 | 拉卡尔穆托 | nulll |
那么上面查询中的表格实际上会给出所有作者的书籍数量。
AUTHOR_NAME | NUMBER_OF_BOOKS |
---|---|
莱昂纳多·夏夏 | 2 |
路易吉·皮兰德罗 | 2 |
埃米利奥·萨尔加里 | 1 |
乔瓦尼·维尔加 | 1 |
乔瓦尼·维尔加 | 1 |
切萨雷·帕韦塞 | 0 |
朱塞佩·托马西·迪·兰佩杜萨 | 0 |
伊塔洛·斯韦沃 | 0 |
结论
在关系型数据库中,数据应该只写一次,所以我们经常会得到多个相互关联的表。LEFT JOIN
AUTHOR_NAME当我们需要分析来自不同表的数据和连接信息时,它是一个非常有用的盟友。享受使用这个强大的工具查询您的数据库的乐趣。