## 資料庫基本概念 ### 什麼是資料庫? 1. 資料表(Table):資料表是資料庫中最基本的資料存儲結構。它是一個二維的資料結構,包含多列和多行,用於存儲特定類型的數據。每個資料表都具有唯一的名稱,用於識別和查詢資料。 - ![](https://hackmd.io/_uploads/SkDb0n7-p.png) 2. Column:資料表中的列代表特定的資料屬性或字段。每列都有一個名稱,用來識別該列的內容,並具有特定的資料類型,例如整數、字符串、日期等。資料表的結構是由它的列定義所確定的。 3. Row:資料表中的行是實際的記錄或數據項。每行包含一個或多個列的值,這些值對應於特定記錄的屬性。例如,如果你有一個資料表用於存儲員工信息,每行代表一個員工,包含姓名、工號、職位等。 4. 主鍵(Primary Key):主鍵是一個用來唯一識別資料表中每一行的列或一組列。主鍵確保了每行的唯一性,並且可以用來查找、連接和修改資料。一個資料表只能有一個主鍵,且主鍵的值不能為 NULL。 - ![](https://hackmd.io/_uploads/rJkwC2XW6.png) 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 * 表示選擇資料表的「所有」欄位 - ![](https://hackmd.io/_uploads/Sk8KBa7-6.png) 2. SELECT column_name 表示只選擇指定欄位 - ![](https://hackmd.io/_uploads/By6AS6m-6.png) 3. 若想指定多個欄位,可用逗號 , 將多個欄位名稱隔開 - ![](https://hackmd.io/_uploads/BJj1LpX-a.png) #### WHERE 子句: 用於篩選查詢結果。 ![](https://hackmd.io/_uploads/S10WU6mWa.png) #### 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()`: 返回排序的排名,如果有相同排名,則排名相同.