# SQL 語法基礎
> [color=#40f1ef][name=LHB阿好伯, JAN 02, 2019 ][:earth_africa:](https://www.facebook.com/LHB0222/)
###### tags: `SQL`
[TOC]
SQL 不需要您將所有大寫的關鍵字都寫成大寫字母,但是作為一種約定,它可以幫助人們從列名和表名中區分出SQL關鍵字,並使查詢更易於閱讀。
# 資料查詢
## 選擇查詢特定欄
要從SQL數據庫檢索數據
我們需要編寫SELECT語句
這些語句通常被俗稱為查詢
查詢本身只是一組語句
聲明我們要查找的數據
在數據庫中的查找位置以及(可選)如何在返回數據之前對其進行轉換
``` SQL
SELECT
欄名1, 欄名2, 欄名3....
FROM
表格名稱;
```
使用星號(*)從表中檢索數據的絕對所有列
``` SQL
SELECT *
FROM 表格名稱;
```
## 選擇有條件的查詢
```SQL
SELECT
欄名1, 欄名2, 欄名3....
FROM 表格名稱
WHERE 條件1
AND/OR 條件2
AND/OR 條件3
:
```
下表為數值可用的運算符
| Operator | 功能 | SQL 範例 |
| :-------------: | :-----------------: | :--------------: |
| =, !=, < <=, >, >= | 標準數值操作 | col_name != 4 |
| BETWEEN ... AND ... | 數值在兩個值的範圍(含)內 | col_name BETWEEN 1.5 AND 10.5 |
| NOT BETWEEN ... AND ... | 數值不在兩個值的範圍(含)內 | col_name NOT BETWEEN 1 AND 10 |
| IN (...) | 存在於列表中存在 | col_name IN (2, 4, 6) |
| NOT IN (...) | 不是在列表中的存在 | col_name NOT IN (1, 3, 5) |
下表為字串可用的運算符
### 萬用字元
| Operator | Condition | Example |
|:--------:|:---------:|:--------:|
| = | ==區分大小==寫精確的字符串比較(注意單等號) | col_name = "abc" |
| != or <> | ==區分大小==寫精確的字符串比較不相等 | col_name != "abcd" |
| LIKE | ==不區分==大小寫精確的字符串比較 | col_name LIKE "ABC" |
| NOT LIKE | ==不區分==大小寫精確的字符串比較不相等 | col_name NOT LIKE "ABCD" |
| % |字符串中的任何地方使用匹配的==零個或多個==字符(僅與LIKE或NOT LIKE)序列 | col_name LIKE "%AT%"\(matches "AT", "ATTIC", "CAT" or even "BATS") |
| _ | 字符串中的任何地方使用,以匹配==單個==字符(僅與LIKE或NOT LIKE) | col_name LIKE "AN_"\(matches "AND", but not "AN") |
| IN (...) | 字串存在於列表中 | col_name IN ("A", "B", "C") |
| NOT IN (...) |字串不存在於列表中 | col_name NOT IN ("D", "E", "F" |
:::danger
必須將所有字串都用引號框起來
以便查詢解析器可以將字符串中的單詞與SQL關鍵字區分
:::
## 過濾和排序查詢結果
即使數據庫中的數據可能是唯一的
但任何特定查詢的結果都可能不是
以電影為例,同一年可以發行許多不同的電影
在這種情況下,SQL提供了一種便捷的方法
可以通過使用DISTINCT 關鍵字來去除具有重複觀測值的行
### 選擇具有唯一結果的查詢
```SQL
SELECT DISTINCT
欄名1, 欄名2, …
FROM
表格名稱
WHERE
條件;
```
### 排序
真實數據庫中的大多數數據沒有特定的列順序
當表的大小增加到數千甚至幾百萬行時
難以閱讀和理解查詢的結果
SQL提供了一種使用ORDER BY子句按給定的列按升序或降序對結果進行排序的方法
```SQL
SELECT
欄名1, 欄名2, …
FROM 表格名稱
WHERE 條件
ORDER BY
欄名 ASC/DESC;
LIMIT 行數限制 OFFSET 跳過行數;
```
:::danger
ASC 升冪排列
DESC 降冪排列
:::
通常與該ORDER BY子句一起使用的另一個子句是LIMITand OFFSET子句
用於向數據庫指定您關注的結果的子集
在LIMIT將結果數量減少到指定行數
以及可選的OFFSET將指定從哪裡開始從計數的結果
```SQL
SELECT
欄名1, 欄名2, …
FROM 表格名稱
WHERE 條件
ORDER BY
欄名 ASC/DESC
LIMIT 行數限制 OFFSET 跳過行數;
```
### GROUP BY 進階篩選 HAVING
我們的查詢變得相當複雜,但是我們幾乎介紹了SELECT查詢的所有重要部分
如果GROUP BY子句在該WHERE子句之後執行(它會過濾要分組的行)
那麼我們如何精確地過濾分組的行呢?
SQL允許通過添加一個附加HAVING子句來執行此操作
該子句專門與該GROUP BY子句一起使用
以允許我們從結果集中過濾分組的行
```SQL
SELECT
欄名1, 欄名2, …
FROM 表格名稱
WHERE 條件
GROUP BY 變數
HAVING 進階篩選條件
ORDER BY
欄名 ASC/DESC;
```
## 使用JOIN的多表查詢
現實世界中的實體數據通常被分解為多個部分
並使用稱為正規化(normalization)的過程存儲在多個正交表中
為了降低資料的「重覆性」
允許數據庫中的數據彼此獨立地增長
使用JOIN查詢中的子句
我們可以使用INNER JOIN將兩個單獨的表中合併行數據
多個表上使用INNER JOIN選擇查詢
```SQL
SELECT
欄名1, 欄名2, …
FROM 表格名稱
INNER JOIN 另一個表格名稱
ON 表格名稱.變數名稱 = 另一個表格名稱.變數名稱
WHERE 條件
ORDER BY
欄名 ASC/DESC
LIMIT 行數限制 OFFSET 跳過行數;
```
### 外部聯接LEFT JOIN,RIGHT JOIN或FULL JOIN
```SQL
SELECT
欄名1, 欄名2, …
FROM 表格名稱
INNER/LEFT/RIGHT/FULL JOIN 另一個表格名稱
ON 表格名稱.變數名稱 = 另一個表格名稱.變數名稱
WHERE 條件
ORDER BY
欄名 ASC/DESC
LIMIT 行數限制 OFFSET 跳過行數;
```
像INNER JOIN這三個新聯接一樣,必須指定要在其上聯接數據的列。
將表A連接到表B時,LEFT JOIN無論是否在B中找到匹配的行,a都會簡單地包含A中的行。
RIGHT JOIN相同,但是相反,無論在A中是否找到匹配項,都將行保留在B中。
FULL JOIN僅僅意味著保留兩個表中的行,而不管另一個表中是否存在匹配的行。


## NULL空值處理
```SQL
SELECT
欄名1, 欄名2, …
FROM 表格名稱
INNER/LEFT/RIGHT/FULL JOIN 另一個表格名稱
ON 表格名稱.變數名稱 = 另一個表格名稱.變數名稱
WHERE 變數名稱 IS NOT NULL/IS NULL
ORDER BY
欄名 ASC/DESC
LIMIT 行數限制 OFFSET 跳過行數;
```
## 常用函數
| Function | Description |
|------|-----|
| COUNT(*), COUNT(column) | A common function used to counts the number of rows in the group if no column name is specified. Otherwise, count the number of rows in the group with non-NULL values in the specified column. |
| MIN(column) | Finds the smallest numerical value in the specified column for all rows in the group. |
| MAX(column) | Finds the largest numerical value in the specified column for all rows in the group. |
| AVG(column) | Finds the average numerical value in the specified column for all rows in the group. |
| SUM(column) | Finds the sum of all numerical values in the specified column for the rows in the group. |
# 完整SQL查詢式
```SQL
SELECT DISTINCT
變數1, 變數2, …,AGG_FUNC(變數), …
FROM 表格名稱
JOIN 另一個表格名稱 /*合併表格*/
ON 表格名稱.變數 = 另一個表格名稱 .變數
WHERE 條件 /*篩選*/
GROUP BY 變數 /*分組*/
HAVING 進階篩選條件
ORDER BY 變數 ASC/DESC /*排序*/
LIMIT 行數限制 OFFSET 跳過行數;
```
🌟全部文章列表
https://hackmd.io/@LHB-0222/AllWritings
https://www.facebook.com/LHB0222/
有疑問想討論的都歡迎於下方留言
喜歡的幫我分享給所有的朋友 \o/
有所錯誤歡迎指教

<style>
html, body, .ui-content {
background-color: #333;
color: #ddd;
}
body > .ui-infobar {
display: none;
}
.ui-view-area > .ui-infobar {
display: block;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
color: #ddd;
}
.markdown-body h1,
.markdown-body h2 {
border-bottom-color: #ffffff69;
}
.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
color: #fff;
}
.markdown-body img {
background-color: transparent;
}
.ui-toc-dropdown .nav>.active:focus>a, .ui-toc-dropdown .nav>.active:hover>a, .ui-toc-dropdown .nav>.active>a {
color: white;
border-left: 2px solid white;
}
.expand-toggle:hover,
.expand-toggle:focus,
.back-to-top:hover,
.back-to-top:focus,
.go-to-bottom:hover,
.go-to-bottom:focus {
color: white;
}
.ui-toc-dropdown {
background-color: #333;
}
.ui-toc-label.btn {
background-color: #191919;
color: white;
}
.ui-toc-dropdown .nav>li>a:focus,
.ui-toc-dropdown .nav>li>a:hover {
color: white;
border-left: 1px solid white;
}
.markdown-body blockquote {
color: #bcbcbc;
}
.markdown-body table tr {
background-color: #5f5f5f;
}
.markdown-body table tr:nth-child(2n) {
background-color: #4f4f4f;
}
.markdown-body code,
.markdown-body tt {
color: #eee;
background-color: rgba(230, 230, 230, 0.36);
}
a,
.open-files-container li.selected a {
color: #5EB7E0;
}
</style>