You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
9.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "9399d7b4767e75068f95ce5c660b285c",
"translation_date": "2025-09-05T12:03:51+00:00",
"source_file": "2-Working-With-Data/05-relational-databases/README.md",
"language_code": "hk"
}
-->
# 使用數據:關係型數據庫
|![ Sketchnote by [(@sketchthedocs)](https://sketchthedocs.dev) ](../../sketchnotes/05-RelationalData.png)|
|:---:|
| 使用數據:關係型數據庫 - _Sketchnote by [@nitya](https://twitter.com/nitya)_ |
你可能曾經使用過電子表格來存儲信息。電子表格由一組行和列組成,其中行包含信息(或數據),列描述信息(有時稱為元數據)。關係型數據庫基於這種表格的核心原則,允許信息分佈在多個表中。這使得我們能處理更複雜的數據,避免重複,並在探索數據時擁有更大的靈活性。讓我們一起探索關係型數據庫的概念。
## [課前測驗](https://ff-quizzes.netlify.app/en/ds/quiz/8)
## 一切從表格開始
關係型數據庫的核心是表格。就像電子表格一樣,表格是由列和行組成的集合。行包含我們希望處理的數據或信息,例如城市名稱或降雨量。列則描述存儲的數據。
讓我們開始探索,建立一個表格來存儲城市的信息。我們可以從城市名稱和國家開始。你可以將其存儲在如下表格中:
| 城市 | 國家 |
| -------- | ------------- |
| 東京 | 日本 |
| 亞特蘭大 | 美國 |
| 奧克蘭 | 新西蘭 |
注意,**城市**、**國家**和**人口**這些列名描述了存儲的數據,每一行都包含一個城市的信息。
## 單一表格方法的局限性
上述表格可能看起來相當熟悉。現在讓我們開始向這個初步的數據庫添加一些額外的數據——年度降雨量以毫米為單位。我們將重點放在2018年、2019年和2020年。如果我們為東京添加數據可能會像這樣
| 城市 | 國家 | 年份 | 降雨量 |
| ----- | ----- | ---- | ------ |
| 東京 | 日本 | 2020 | 1690 |
| 東京 | 日本 | 2019 | 1874 |
| 東京 | 日本 | 2018 | 1445 |
你注意到我們的表格有什麼問題嗎?你可能會注意到我們重複了城市名稱和國家多次。這可能會佔用相當多的存儲空間,而且多次複製是完全不必要的。畢竟,東京的名字只有一個。
好吧,讓我們嘗試另一種方法。讓我們為每一年添加新的列:
| 城市 | 國家 | 2018 | 2019 | 2020 |
| -------- | ------------- | ---- | ---- | ---- |
| 東京 | 日本 | 1445 | 1874 | 1690 |
| 亞特蘭大 | 美國 | 1779 | 1111 | 1683 |
| 奧克蘭 | 新西蘭 | 1386 | 942 | 1176 |
雖然這避免了行的重複,但也帶來了其他挑戰。我們每次有新的一年都需要修改表格的結構。此外,隨著數據的增長,將年份作為列會使檢索和計算數值變得更加困難。
這就是為什麼我們需要多個表格和關係。通過拆分數據,我們可以避免重複,並在處理數據時擁有更大的靈活性。
## 關係的概念
讓我們回到數據,確定如何拆分它。我們知道我們希望存儲城市的名稱和國家,因此這可能最適合存儲在一個表中。
| 城市 | 國家 |
| -------- | ------------- |
| 東京 | 日本 |
| 亞特蘭大 | 美國 |
| 奧克蘭 | 新西蘭 |
但在創建下一個表之前我們需要確定如何引用每個城市。我們需要某種形式的標識符、ID或在技術數據庫術語中主鍵。主鍵是一個用於標識表中某一特定行的值。雖然這可以基於某個值本身例如我們可以使用城市的名稱但它幾乎應該是一個數字或其他標識符。我們不希望ID發生變化因為這會破壞關係。在大多數情況下主鍵或ID通常是一個自動生成的數字。
> ✅ 主鍵通常縮寫為PK
### 城市表
| city_id | 城市 | 國家 |
| ------- | -------- | ------------- |
| 1 | 東京 | 日本 |
| 2 | 亞特蘭大 | 美國 |
| 3 | 奧克蘭 | 新西蘭 |
> ✅ 在本課程中你會注意到我們交替使用“id”和“主鍵”這些術語。這些概念同樣適用於DataFrames你稍後會探索它們。DataFrames不使用“主鍵”這一術語但你會注意到它們的行為非常相似。
有了城市表我們可以存儲降雨量。與其重複城市的完整信息我們可以使用ID。我們還應確保新創建的表也有一個*id*列因為所有表都應有一個ID或主鍵。
### 降雨量表
| rainfall_id | city_id | 年份 | 降雨量 |
| ----------- | ------- | ---- | ------ |
| 1 | 1 | 2018 | 1445 |
| 2 | 1 | 2019 | 1874 |
| 3 | 1 | 2020 | 1690 |
| 4 | 2 | 2018 | 1779 |
| 5 | 2 | 2019 | 1111 |
| 6 | 2 | 2020 | 1683 |
| 7 | 3 | 2018 | 1386 |
| 8 | 3 | 2019 | 942 |
| 9 | 3 | 2020 | 1176 |
注意新創建的**降雨量**表中的**city_id**列。這一列包含引用**城市**表中ID的值。在技術關係型數據術語中這被稱為**外鍵**;它是來自另一個表的主鍵。你可以將其簡單理解為一個引用或指針。**city_id** 1引用的是東京。
> [!NOTE] 外鍵通常縮寫為FK
## 檢索數據
將數據分成兩個表後你可能會想知道如何檢索它。如果我們使用像MySQL、SQL Server或Oracle這樣的關係型數據庫我們可以使用一種叫做結構化查詢語言SQL的語言。SQL有時讀作sequel是一種標準語言用於在關係型數據庫中檢索和修改數據。
要檢索數據,你可以使用命令`SELECT`。其核心是,你**選擇**想要查看的列,**從**它們所在的表中檢索。如果你只想顯示城市的名稱,可以使用以下命令:
```sql
SELECT city
FROM cities;
-- Output:
-- Tokyo
-- Atlanta
-- Auckland
```
`SELECT`是列出列名的地方,`FROM`是列出表名的地方。
> [NOTE] SQL語法不區分大小寫這意味著`select`和`SELECT`是相同的。然而根據你使用的數據庫類型列名和表名可能區分大小寫。因此最佳做法是始終將編程中的所有內容視為區分大小寫。在編寫SQL查詢時常見的約定是將關鍵字全部用大寫字母表示。
上述查詢將顯示所有城市。假設我們只想顯示新西蘭的城市。我們需要某種形式的篩選器。SQL中的關鍵字是`WHERE`,即“某些條件為真”。
```sql
SELECT city
FROM cities
WHERE country = 'New Zealand';
-- Output:
-- Auckland
```
## 數據的連接
到目前為止,我們只從單個表中檢索數據。現在我們希望將**城市**和**降雨量**中的數據結合起來。這可以通過*連接*它們來完成。你將有效地在兩個表之間創建一個接縫,並匹配每個表中的列值。
在我們的例子中,我們將匹配**降雨量**表中的**city_id**列和**城市**表中的**city_id**列。這將匹配降雨量值與其相應的城市。我們將執行的連接類型稱為*內部連接*,這意味著如果某些行與另一個表中的任何內容不匹配,它們將不會顯示。在我們的例子中,每個城市都有降雨量,因此所有內容都會顯示。
讓我們檢索2019年所有城市的降雨量。
我們將分步完成。第一步是通過指明接縫的列來連接數據——如前所述的**city_id**。
```sql
SELECT cities.city
rainfall.amount
FROM cities
INNER JOIN rainfall ON cities.city_id = rainfall.city_id
```
我們已經突出顯示了我們想要的兩列,以及我們希望通過**city_id**連接表的事實。現在我們可以添加`WHERE`語句來篩選出僅2019年的數據。
```sql
SELECT cities.city
rainfall.amount
FROM cities
INNER JOIN rainfall ON cities.city_id = rainfall.city_id
WHERE rainfall.year = 2019
-- Output
-- city | amount
-- -------- | ------
-- Tokyo | 1874
-- Atlanta | 1111
-- Auckland | 942
```
## 總結
關係型數據庫的核心是將信息分成多個表,然後將其重新結合以進行顯示和分析。這提供了高度的靈活性來進行計算或以其他方式操作數據。你已經了解了關係型數據庫的核心概念,以及如何在兩個表之間進行連接。
## 🚀 挑戰
網絡上有許多關係型數據庫可供使用。你可以使用上述技能來探索數據。
## 課後測驗
## [課後測驗](https://ff-quizzes.netlify.app/en/ds/quiz/9)
## 回顧與自學
[Microsoft Learn](https://docs.microsoft.com/learn?WT.mc_id=academic-77958-bethanycheum)上有許多資源可供你繼續探索SQL和關係型數據庫的概念
- [描述關係型數據的概念](https://docs.microsoft.com//learn/modules/describe-concepts-of-relational-data?WT.mc_id=academic-77958-bethanycheum)
- [開始使用Transact-SQL進行查詢](https://docs.microsoft.com//learn/paths/get-started-querying-with-transact-sql?WT.mc_id=academic-77958-bethanycheum)Transact-SQL是SQL的一個版本
- [Microsoft Learn上的SQL內容](https://docs.microsoft.com/learn/browse/?products=azure-sql-database%2Csql-server&expanded=azure&WT.mc_id=academic-77958-bethanycheum)
## 作業
[作業標題](assignment.md)
---
**免責聲明**
此文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤詮釋概不負責。