## 資料庫基本概念
### 什麼是資料庫?
1. 資料表(Table):資料表是資料庫中最基本的資料存儲結構。它是一個二維的資料結構,包含多列和多行,用於存儲特定類型的數據。每個資料表都具有唯一的名稱,用於識別和查詢資料。
- 
2. Column:資料表中的列代表特定的資料屬性或字段。每列都有一個名稱,用來識別該列的內容,並具有特定的資料類型,例如整數、字符串、日期等。資料表的結構是由它的列定義所確定的。
3. Row:資料表中的行是實際的記錄或數據項。每行包含一個或多個列的值,這些值對應於特定記錄的屬性。例如,如果你有一個資料表用於存儲員工信息,每行代表一個員工,包含姓名、工號、職位等。
4. 主鍵(Primary Key):主鍵是一個用來唯一識別資料表中每一行的列或一組列。主鍵確保了每行的唯一性,並且可以用來查找、連接和修改資料。一個資料表只能有一個主鍵,且主鍵的值不能為 NULL。
- 
5. 外鍵(Foreign Key):外鍵是一個用來建立表之間關聯的列。它建立了一個參照其他資料表的關聯,通常用於維護資料之間的完整性和關聯。外鍵的值是另一個資料表中的主鍵,用於確保關聯的一致性。
### 數據模型分類
#### 關聯資料庫 (Relational Database):
- 結構化資料存儲: 關聯資料庫以表格形式存儲數據,每個表格包含列和行,具有固 定的結構,並使用結構化查詢語言(SQL)來查詢和操作數據。
- 表格和列: 關聯資料庫使用表格(表)來組織數據,每個表格包含一組列,每列定義了特定的數據類型
- 關聯: 關聯資料庫通過主鍵和外鍵來建立表之間的關聯,以實現數據的一致性和參照完整性。
- 廣泛使用場景: 關聯資料庫適用於需要複雜查詢、多表關聯、事務處理的場景,如企業應用、交易處理系統、銀行系統等。
#### 非關聯資料庫 (Non-relational Database,NoSQL Database):
- 彈性數據存儲: 非關聯資料庫允許靈活的數據存儲,可以存儲半結構化或非結構化數據,不需要固定的表結構。
- 多種數據模型: NoSQL 資料庫支持多種數據模型,如文件數據庫、列族數據庫、鍵值對數據庫和圖形數據庫。
-
> 總之,關聯資料庫和非關聯資料庫之間的主要區別在於數據模型、結構、查詢語言。選擇使用哪種類型的資料庫取決於您的項目需求、數據性質和性能要求。有時候,混合使用關聯資料庫和非關聯資料庫也是一種有效的策略。
#### 什麼是結構化
- 結構化資料是指以一種固定格式或結構來組織和存儲的數據。這種類型的數據具有清晰的結構,每個數據元素都有特定的字段和值,這些字段的名稱和數據類型是預定義的。結構化數據通常以表格形式存儲,每個數據項目都位於特定的列和行中。這種結構使得數據容易被組織、查詢和分析。
### [什麼是 key](https://medium.com/pierceshih/%E7%AD%86%E8%A8%98-%E8%B3%87%E6%96%99%E9%97%9C%E8%81%AF%E7%9A%84%E4%B8%89%E7%A8%AE%E9%97%9C%E4%BF%82-245152c093da)
### [資料庫的正規化](https://blog.build-school.com/2022/07/22/%E8%B3%87%E6%96%99%E5%BA%AB%E6%AD%A3%E8%A6%8F%E5%8C%96%E7%AD%86%E8%A8%98/)
## SQL(Structured Query Language):
- 定義:SQL(Structured Query Language,結構化查詢語言)是一種用於管理和操作關聯式數據庫系統的標準化查詢語言。SQL 用於執行各種數據庫操作,包括檢索數據、插入、更新和刪除數據,以及創建和管理數據庫對象(如表、視圖、索引等)。
## 資料庫 sample
- [sample](https://www.sqlitetutorial.net/sqlite-sample-database/)
## 使用環境
- [SQLlite](https://www.runoob.com/sqlite/sqlite-installation.html)
### 基本 SQL 語法: 掌握 SQL 的基本語法
- 具體而言,資料操作 可細分為
- 創造 Create
- 查詢 Read
- 更新 Update
- 刪除 Delete
### 查詢
#### SELECT FROM: 用於查詢數據。
1. SELECT 與 FROM 敘述是從指定的資料表中選擇欄位的查詢語法,SELECT * 表示選擇資料表的「所有」欄位
- 
2. SELECT column_name 表示只選擇指定欄位
- 
3. 若想指定多個欄位,可用逗號 , 將多個欄位名稱隔開
- 
#### WHERE 子句: 用於篩選查詢結果。

#### Operator
- 比較運算符:
```sql=
=:等於(相等)。
<> 或 !=:不等於。
<:小於。
>:大於。
<=:小於等於。
>=:大於等於。
BETWEEN:在某個範圍內。
LIKE:模糊查詢,用於匹配模式。
IN:在某個值集合中。
```
- 邏輯運算符:
```sql=
AND:邏輯與(兩個條件都必須為真)。
OR:邏輯或(至少一個條件為真)。
NOT:邏輯非(取反)。
```
- 算術運算符:
```sql=
+:加法。
-:減法。
*:乘法。
/:除法。
%:取餘數。
```
#### ORDER BY 子句: 用於排序查詢結果。
- ORDER BY 子句用於對 SQL 查詢的結果進行排序。你可以使用 ORDER BY 子句根據一個或多個列的值來指定排序順序。以下是 ORDER BY 子句的基本用法:
```sql=
SELECT column1, column2, ...
FROM table_name
ORDER BY column1 [ASC | DESC], column2 [ASC | DESC], ...;
```
- SELECT column1, column2, ...: 定義你想要檢索的列。
- FROM table_name: 指定你要檢索數據的資料表。
- ORDER BY: 這是排序子句的開始。
- column1, column2, ...: 這是你想要用來排序的列的名稱,你可以指定多個列以建立複雜的排序。
- [ASC | DESC]: 可選的,表示排序順序。默認情況下是升序(ASC),即從小到大排序。如果你想降序排序(從大到小),則使用 DESC。
- 升序排序(默認情況下):
```sql=
sql
Copy code
SELECT FirstName, LastName
FROM employees
ORDER BY LastName, FirstName;
```
- 降序排序:
```sql=
sql
Copy code
SELECT ProductName, UnitPrice
FROM products
ORDER BY UnitPrice DESC;
```
- 多列排序:
```sql=
sql
Copy code
SELECT CustomerName, OrderDate, TotalAmount
FROM orders
ORDER BY CustomerName, OrderDate DESC;
```
#### JOIN 操作: 用於聯接多個資料表。
- INNER JOIN:
- INNER JOIN 返回兩個資料表中匹配行的交集。這是最常見的 JOIN 類型。
```sql=
SELECT employees.EmployeeName, departments.DepartmentName
FROM employees
INNER JOIN departments ON employees.DepartmentId = departments.DepartmentId;
```
- LEFT JOIN(或 LEFT OUTER JOIN):
- LEFT JOIN 返回左邊資料表中的所有行,以及右邊資料表中與左邊資料表匹配的行。如果右邊資料表中沒有匹配的行,則返回 NULL。
```sql=
SELECT customers.CustomerName, orders.OrderDate
FROM customers
LEFT JOIN orders ON customers.CustomerID = orders.CustomerID;
```
- RIGHT JOIN(或 RIGHT OUTER JOIN):
- RIGHT JOIN 返回右邊資料表中的所有行,以及左邊資料表中與右邊資料表匹配的行。如果左邊資料表中沒有匹配的行,則返回 NULL。
```sql=
SELECT orders.OrderDate, customers.CustomerName
FROM orders
RIGHT JOIN customers ON orders.CustomerID = customers.CustomerID;
```
- FULL JOIN(或 FULL OUTER JOIN):
- FULL JOIN 返回左邊和右邊資料表中的所有行,如果沒有匹配的行,則返回 NULL。
```sql=
SELECT employees.EmployeeName, departments.DepartmentName
FROM employees
FULL JOIN departments ON employees.DepartmentId = departments.DepartmentId;
```
- SELF JOIN:
- SELF JOIN 是一個特殊的情況,其中你加入資料表的不同行,通常用於處理層次結構的資料,如組織樹。
```sql=
SELECT e1.EmployeeName AS Employee, e2.EmployeeName AS Manager
FROM employees e1
LEFT JOIN employees e2 ON e1.ManagerID = e2.EmployeeID;
```
- 這些是 JOIN 操作的基本類型,它們允許你根據不同的關聯條件合併資料表,以執行更複雜的查詢。你應根據你的資料表結構和查詢需求選擇合適的 JOIN 類型。
#### GROUP BY 子句
- 用於分組數據。
- having
- HAVING 子句是 SQL 中用於篩選聚合查詢結果的一個子句。它通常與 GROUP BY 子句一起使用,用於對分組後的數據應用過濾條件。HAVING 子句允許你篩選聚合值,而 WHERE 子句用於篩選行級數據。
```sql=
SELECT column1, column2, aggregate_function(column3)
FROM table_name
GROUP BY column1, column2
HAVING condition;
```
- SELECT 子句列出了你想要檢索的列,包括聚合函數(如 SUM、COUNT、AVG 等)。
- FROM 子句指定了你要查詢的資料表。
- GROUP BY 子句用來指定分組的條件,列出了根據哪些列進行分組。
- HAVING 子句用來篩選根據 GROUP BY 分組後的結果。這裡的 condition 是一個運算式,如果運算式的結果為真,則相應的分組將包含在結果中。
```sql=
SELECT product_id, SUM(quantity * price) AS total_sales
FROM orders
GROUP BY product_id
HAVING SUM(quantity * price) > 1000;
```
#### Partition
- PARTITION BY 子句通常與分析函數一起使用,它允許你將查詢結果分為多個分區,然後在每個分區內應用分析函數。這對處理有組織結構的資料或需要按特定條件分組的查詢非常有用。
- 以下是一個簡單的示例,說明如何使用 PARTITION BY:
- 假設你有一個 sales 資料表,包含銷售員工的銷售金額以及他們所屬的部門。你想查詢每個部門內每位銷售員工的銷售金額排名。這就是你可以使用 PARTITION BY 的情況:
```sql=
SELECT
Department,
Salesperson,
SalesAmount,
RANK() OVER (PARTITION BY Department ORDER BY SalesAmount DESC) AS SalesRank
FROM sales;
```
- 在這個查詢中,PARTITION BY Department 表示你要將結果集分為多個分區,每個分區代表一個不同的部門。然後,RANK() OVER (PARTITION BY Department ORDER BY SalesAmount DESC) 部分選擇在每個部門內按銷售金額遞減排序,並賦予每位銷售員工在其部門內的銷售金額排名。
- 這是 PARTITION BY 的基本用法,它允許你在結果集的分區內應用分析函數,以便更好地理解和分析資料。你可以根據不同的情況和需求調整 PARTITION BY 子句。
#### with
- "WITH" 子句在 SQL 中用於建立臨時的查詢結果集,也稱為公共表達式(Common Table Expression,CTE)。這些臨時結果集可以在查詢中多次引用,從而使複雜查詢更易於閱讀和維護。
- "WITH" 子句的基本語法如下:
```sql=
WITH cte_name (column1, column2, ...) AS (
-- 查詢語句
SELECT ...
)
-- 主查詢
SELECT ...
```
- 以下是 "WITH" 子句的一些常見用法:
- 建立公共表達式(CTE):
- 使用 "WITH" 子句,你可以創建一個具有列名的臨時表達式,這個表達式可以在查詢中多次引用。例如:
```sql=
sql
Copy code
WITH EmployeeCTE (EmployeeName, Salary) AS (
SELECT Name, Salary FROM Employees
)
SELECT EmployeeName, Salary
FROM EmployeeCTE
WHERE Salary > 50000;
```
- 這裡,"EmployeeCTE" 是一個臨時表達式,用於存儲 Employee 表中的數據,然後在後續查詢中引用。
### 常用函數
1. **聚合函數:**
- `COUNT()`: 計算行數或某列的非 NULL 值的數量。
- `SUM()`: 計算某列的數值總和。
- `AVG()`: 計算某列的平均值。
- `MAX()`: 找出某列的最大值。
- `MIN()`: 找出某列的最小值.
2. **字符串函數:**
- `CONCAT()`: 連接兩個或多個字符串。
- `LENGTH()` 或 `LEN()`: 返回字符串的長度。
- `UPPER()`: 轉換字符串為大寫。
- `LOWER()`: 轉換字符串為小寫。
- `SUBSTRING()`: 提取部分字符串.
3. **日期和時間函數:**
- `CURRENT_DATE` 或 `NOW()`: 返回當前日期和時間。
- `DATE()`: 提取日期部分。
- `TIME()`: 提取時間部分。
- `YEAR()`, `MONTH()`, `DAY()`: 提取年、月、日。
- `DATEDIFF()`: 計算兩個日期之間的天數差異.
4. **條件函數:**
- `IF()`: 如果條件為真,返回一個值,否則返回另一個值。
- `CASE WHEN`: 用於根據不同條件返回不同的值.
5. **數學函數:**
- `ABS()`: 返回絕對值。
- `ROUND()`: 四捨五入到指定的小數位數。
- `CEIL()` 或 `FLOOR()`: 分別返回不小於和不大於指定數字的整數.
6. **型別轉換函數:**
- `CAST()`: 將一種數據型別轉換為另一種數據型別。
- `CONVERT()`: 用於數據型別轉換,具體語法取決於SQL實現.
7. **空值處理函數:**
- `IS NULL`: 用於檢查是否為NULL。
- `COALESCE()`: 返回第一個非NULL值.
8. **排序函數:**
- `ORDER BY`: 用於排序查詢結果。
- `GROUP BY`: 用於分組查詢結果.
9. **窗口函數:**
- `ROW_NUMBER()`: 為查詢結果集的行賦予唯一的序號。
- `RANK()`: 返回排序的排名。
- `DENSE_RANK()`: 返回排序的排名,如果有相同排名,則排名相同.