# SQL 入門

> 基本查詢

郭耀仁

```python
# 連結資料庫
import sqlite3
import pandas as pd
from test_queries.test_queries_02 import extract_test_queries as etq

conn_twelection = sqlite3.connect('twelection.db')
conn_nba = sqlite3.connect('nba.db')
```

## 摘要

- SQL 風格指南
- 資料型態
- 延續 `SELECT` 和 `FROM`
- 隨堂練習
- 隨堂練習參考解答

## SQL 風格指南

## 什麼是風格指南

> 程式語言的風格指南是一份描述在撰寫指定程式語言風格規範的文件，風格指南會隨著語言、團隊習慣的不同，而有不同的形式與內涵。

## 為什麼風格指南

> 一個被部署在正式環境的應用程式應該要看起來像是由一位軟體工程師所撰寫出來的，即便是由數百名軟體工程師合力撰寫。這樣的程式原始碼能被更良好地維護、減少溝通不效率並降低系統出錯的風險。

## 如果對風格指南不滿意該怎麼辦才好

> 假如剛加入團隊時發現對於風格指南不甚滿意，請先保持靜默，等到過了一段時間在團隊中已經建立的聲譽和信賴感，再針對具有「明顯效益」的風格指南提出建議。

## 「普遍」的 SQL 風格指南

Source: <https://giphy.com/>

## 課程將採用 [Simon Holywell](https://www.simonholywell.com/) 的 SQL 風格指南

Source: <https://www.sqlstyle.guide/>

## 建議遵守的部分

- 善用「空白」與「縮排」提升可讀性
- 使用 ISO-8601 的日期時間格式 `YYYY-MM-DD HH:MM:SS.SSSSS`
- 為了移植便利性，盡可能使用標準 SQL 而非特定 DBMS 的功能或函式
- 善用註解
    - `/**/` 用來做多行註解
    - `--` 用來做單行註解

Source: Google Search

## 命名的原則

- 由英文字母起始並且不要以底線 `_` 終結
- 不得使用保留字
- 使用英文字母與數字，並且以底線 `_` 分隔單字
- 不要使用多個底線例如 `__`
- 盡量只使用很直觀的縮寫作為命名

## 標準 SQL 的保留字有哪些

<https://www.w3schools.com/sql/sql_ref_keywords.asp>

Source: <https://www.w3schools.com/>

## 以全大寫來撰寫保留字：`SELECT * FROM table_name`

## 需要換行的時候採「靠右對齊」

```python
sql_query = """
SELECT *
  FROM teams
 WHERE confName = 'East';
"""
```

```python
pd.read_sql(sql_query, conn_nba)
```

      isNBAFranchise
      isAllStar
      city
      altCityName
      fullName
      tricode
      teamId
      nickname
      urlName
      teamShortName
      confName
      divName

      0
      True
      False
      Atlanta
      Atlanta
      Atlanta Hawks
      ATL
      1610612737
      Hawks
      hawks
      Atlanta
      East
      Southeast

      1
      True
      False
      Boston
      Boston
      Boston Celtics
      BOS
      1610612738
      Celtics
      celtics
      Boston
      East
      Atlantic

      2
      True
      False
      Cleveland
      Cleveland
      Cleveland Cavaliers
      CLE
      1610612739
      Cavaliers
      cavaliers
      Cleveland
      East
      Central

      3
      True
      False
      Chicago
      Chicago
      Chicago Bulls
      CHI
      1610612741
      Bulls
      bulls
      Chicago
      East
      Central

      4
      True
      False
      Miami
      Miami
      Miami Heat
      MIA
      1610612748
      Heat
      heat
      Miami
      East
      Southeast

      5
      True
      False
      Milwaukee
      Milwaukee
      Milwaukee Bucks
      MIL
      1610612749
      Bucks
      bucks
      Milwaukee
      East
      Central

      6
      True
      False
      Brooklyn
      Brooklyn
      Brooklyn Nets
      BKN
      1610612751
      Nets
      nets
      Brooklyn
      East
      Atlantic

      7
      True
      False
      New York
      New York
      New York Knicks
      NYK
      1610612752
      Knicks
      knicks
      New York
      East
      Atlantic

      8
      True
      False
      Orlando
      Orlando
      Orlando Magic
      ORL
      1610612753
      Magic
      magic
      Orlando
      East
      Southeast

      9
      True
      False
      Indiana
      Indiana
      Indiana Pacers
      IND
      1610612754
      Pacers
      pacers
      Indiana
      East
      Central

      10
      True
      False
      Philadelphia
      Philadelphia
      Philadelphia 76ers
      PHI
      1610612755
      76ers
      sixers
      Philadelphia
      East
      Atlantic

      11
      True
      False
      Toronto
      Toronto
      Toronto Raptors
      TOR
      1610612761
      Raptors
      raptors
      Toronto
      East
      Atlantic

      12
      True
      False
      Washington
      Washington
      Washington Wizards
      WAS
      1610612764
      Wizards
      wizards
      Washington
      East
      Southeast

      13
      True
      False
      Detroit
      Detroit
      Detroit Pistons
      DET
      1610612765
      Pistons
      pistons
      Detroit
      East
      Central

      14
      True
      False
      Charlotte
      Charlotte
      Charlotte Hornets
      CHA
      1610612766
      Hornets
      hornets
      Charlotte
      East
      Southeast

## 何時加入空白

- 在 `=` 的前後
- 在 `,` 之後

```python
sql_query = """
SELECT *
  FROM teams
 WHERE divName IN ('Atlantic', 'Southeast');
"""
```

```python
pd.read_sql(sql_query, conn_nba)
```

      isNBAFranchise
      isAllStar
      city
      altCityName
      fullName
      tricode
      teamId
      nickname
      urlName
      teamShortName
      confName
      divName

      0
      True
      False
      Atlanta
      Atlanta
      Atlanta Hawks
      ATL
      1610612737
      Hawks
      hawks
      Atlanta
      East
      Southeast

      1
      True
      False
      Boston
      Boston
      Boston Celtics
      BOS
      1610612738
      Celtics
      celtics
      Boston
      East
      Atlantic

      2
      True
      False
      Miami
      Miami
      Miami Heat
      MIA
      1610612748
      Heat
      heat
      Miami
      East
      Southeast

      3
      True
      False
      Brooklyn
      Brooklyn
      Brooklyn Nets
      BKN
      1610612751
      Nets
      nets
      Brooklyn
      East
      Atlantic

      4
      True
      False
      New York
      New York
      New York Knicks
      NYK
      1610612752
      Knicks
      knicks
      New York
      East
      Atlantic

      5
      True
      False
      Orlando
      Orlando
      Orlando Magic
      ORL
      1610612753
      Magic
      magic
      Orlando
      East
      Southeast

      6
      True
      False
      Philadelphia
      Philadelphia
      Philadelphia 76ers
      PHI
      1610612755
      76ers
      sixers
      Philadelphia
      East
      Atlantic

      7
      True
      False
      Toronto
      Toronto
      Toronto Raptors
      TOR
      1610612761
      Raptors
      raptors
      Toronto
      East
      Atlantic

      8
      True
      False
      Washington
      Washington
      Washington Wizards
      WAS
      1610612764
      Wizards
      wizards
      Washington
      East
      Southeast

      9
      True
      False
      Charlotte
      Charlotte
      Charlotte Hornets
      CHA
      1610612766
      Hornets
      hornets
      Charlotte
      East
      Southeast

## 命名與別名

- 表格的命名以「複數」名詞為主
- 變數的命名以「單數」名詞為主
- 建立別名時用 `AS`

```python
sql_query = """
SELECT fullName AS team_name
  FROM teams
 LIMIT 5;
"""
```

```python
pd.read_sql(sql_query, conn_nba)
```

      team_name

      0
      Atlanta Hawks

      1
      Boston Celtics

      2
      Cleveland Cavaliers

      3
      New Orleans Pelicans

      4
      Chicago Bulls

## 資料型態

## 使用 `PRAGMA TABLE_INFO(table_name)` 暸解表格的資料型態

注意，這是 SQLite 資料庫系統專屬的語法，不同的資料庫系統具有自己語法。

```python
sql_query = """
PRAGMA TABLE_INFO(careerSummaries);
"""
```

```python
pd.read_sql(sql_query, conn_nba)
```

      cid
      name
      type
      notnull
      dflt_value
      pk

      0
      0
      personId
      INTEGER
      0
      None
      1

      1
      1
      tpp
      REAL
      0
      None
      0

      2
      2
      ftp
      REAL
      0
      None
      0

      3
      3
      fgp
      REAL
      0
      None
      0

      4
      4
      ppg
      REAL
      0
      None
      0

      5
      5
      rpg
      REAL
      0
      None
      0

      6
      6
      apg
      REAL
      0
      None
      0

      7
      7
      bpg
      REAL
      0
      None
      0

      8
      8
      mpg
      REAL
      0
      None
      0

      9
      9
      spg
      REAL
      0
      None
      0

      10
      10
      assists
      INTEGER
      0
      None
      0

      11
      11
      blocks
      INTEGER
      0
      None
      0

      12
      12
      steals
      INTEGER
      0
      None
      0

      13
      13
      turnovers
      INTEGER
      0
      None
      0

      14
      14
      offReb
      INTEGER
      0
      None
      0

      15
      15
      defReb
      INTEGER
      0
      None
      0

      16
      16
      totReb
      INTEGER
      0
      None
      0

      17
      17
      fgm
      REAL
      0
      None
      0

      18
      18
      fga
      REAL
      0
      None
      0

      19
      19
      tpm
      REAL
      0
      None
      0

      20
      20
      tpa
      REAL
      0
      None
      0

      21
      21
      ftm
      REAL
      0
      None
      0

      22
      22
      fta
      REAL
      0
      None
      0

      23
      23
      pFouls
      REAL
      0
      None
      0

      24
      24
      points
      INTEGER
      0
      None
      0

      25
      25
      gamesPlayed
      INTEGER
      0
      None
      0

      26
      26
      gamesStarted
      INTEGER
      0
      None
      0

      27
      27
      plusMinus
      REAL
      0
      None
      0

      28
      28
      min
      REAL
      0
      None
      0

      29
      29
      dd2
      REAL
      0
      None
      0

      30
      30
      td3
      REAL
      0
      None
      0

## 使用 `TYPEOF()` 函式暸解欄位的資料型態

注意，這是 SQLite 資料庫系統專屬的函式，不同的資料庫系統具有自己的對應函式。

```python
sql_query = """
SELECT TYPEOF(points) AS points_dt,
       TYPEOF(ppg) AS ppg_dt
  FROM careerSummaries
 LIMIT 1;
"""
pd.read_sql(sql_query, conn_nba)
```

      points_dt
      ppg_dt

      0
      integer
      real

## 資料型態的分類由資料庫系統決定，但大致都有對應這些型態

- 數值
- 文字
- 遺漏值
- 布林
- 日期與時間

## 使用 `CAST(column_name AS data_type)` 在查詢時轉換欄位的資料型態

```python
sql_query = """
SELECT TYPEOF(points) AS points_int,
       TYPEOF(CAST(points AS REAL)) AS points_real
  FROM careerSummaries
 LIMIT 1;
"""
pd.read_sql(sql_query, conn_nba)
```

      points_int
      points_real

      0
      integer
      real

## 查詢特定資料庫系統的資料型態

<https://www.sqlite.org/datatype3.html>

Source: <https://www.sqlite.org/>

## 不同資料型態能夠對應各自的運算符

- 文字可以使用 `||` 運算符做連結
- 數值可以使用 `+`, `-`, `*`, `/`, `%`

```python
sql_query = """
SELECT firstName || " " || lastName AS full_name
  FROM players;
"""
```

```python
pd.read_sql(sql_query, conn_nba)
```

      full_name

      0
      Vince Carter

      1
      Tyson Chandler

      2
      LeBron James

      3
      Carmelo Anthony

      4
      Kyle Korver

      ...
      ...

      499
      Matt Thomas

      500
      Tariq Owens

      501
      Javonte Green

      502
      Juwan Morgan

      503
      Matt Mooney

504 rows × 1 columns

## 數值運算符的計算順序

1. 小括號
2. 次方與根號
3. 乘法、除法與餘數
4. 加法與減法

## 例如計算身體質量指數（BMI）的公式

\begin{equation}
BMI = \frac{weight_{kg}}{height_m^{2}}
\end{equation}

```python
sql_query = """
SELECT firstName,
       lastName,
       weightKilograms / (heightMeters*heightMeters) AS bmi
  FROM players
 LIMIT 10;
"""
```

```python
pd.read_sql(sql_query, conn_nba)
```

      firstName
      lastName
      bmi

      0
      Vince
      Carter
      25.456586

      1
      Tyson
      Chandler
      23.496220

      2
      LeBron
      James
      26.722594

      3
      Carmelo
      Anthony
      26.207867

      4
      Kyle
      Korver
      23.811292

      5
      Udonis
      Haslem
      25.868136

      6
      Dwight
      Howard
      27.782914

      7
      Andre
      Iguodala
      24.869911

      8
      JR
      Smith
      25.456586

      9
      Trevor
      Ariza
      23.659880

## SQLite 的常用函式

<https://www.sqlitetutorial.net/sqlite-functions/>

Source: <https://www.sqlitetutorial.net/>

## 延續 `SELECT` 和 `FROM`

## 使用 `ORDER BY` 排序查詢結果

- 預設遞增（`ASC`）排序，不需要指定
- 遞減（`DESC`）排序要指定

```python
sql_query = """
SELECT personId,
       points
  FROM careerSummaries
 ORDER BY points;
"""
```

```python
pd.read_sql(sql_query, conn_nba)
```

      personId
      points

      0
      1629007
      NaN

      1
      1629624
      NaN

      2
      1629626
      NaN

      3
      1629685
      NaN

      4
      1629719
      NaN

      ...
      ...
      ...

      499
      201935
      20723.0

      500
      201142
      22940.0

      501
      1713
      25728.0

      502
      2546
      26314.0

      503
      2544
      34087.0

504 rows × 2 columns

```python
sql_query = """
SELECT personId,
       points
  FROM careerSummaries
 ORDER BY points DESC;
"""
pd.read_sql(sql_query, conn_nba)
```

      personId
      points

      0
      2544
      34087.0

      1
      2546
      26314.0

      2
      1713
      25728.0

      3
      201142
      22940.0

      4
      201935
      20723.0

      ...
      ...
      ...

      499
      1629624
      NaN

      500
      1629626
      NaN

      501
      1629685
      NaN

      502
      1629719
      NaN

      503
      1629734
      NaN

504 rows × 2 columns

## 排序並不僅限於一個變數

```python
sql_query = """
SELECT firstName,
       lastName,
       dateOfBirthUTC
  FROM players
 ORDER BY firstName,
          dateOfBirthUTC DESC;
"""
```

```python
pd.read_sql(sql_query, conn_nba)
```

      firstName
      lastName
      dateOfBirthUTC

      0
      Aaron
      Holiday
      1996-09-30

      1
      Aaron
      Gordon
      1995-09-16

      2
      Abdel
      Nader
      1993-09-25

      3
      Adam
      Mokoka
      1998-07-18

      4
      Admiral
      Schofield
      1997-03-30

      ...
      ...
      ...
      ...

      499
      Zach
      Collins
      1997-11-19

      500
      Zach
      LaVine
      1995-03-10

      501
      Zhaire
      Smith
      1999-06-04

      502
      Zion
      Williamson
      2000-07-06

      503
      Zylan
      Cheatham
      1995-11-17

504 rows × 3 columns

## 使用 `WHERE` 篩選觀測值

```python
sql_query = """
SELECT fullName
  FROM teams
 WHERE confName = 'East';
"""
```

```python
pd.read_sql(sql_query, conn_nba)
```

      fullName

      0
      Atlanta Hawks

      1
      Boston Celtics

      2
      Cleveland Cavaliers

      3
      Chicago Bulls

      4
      Miami Heat

      5
      Milwaukee Bucks

      6
      Brooklyn Nets

      7
      New York Knicks

      8
      Orlando Magic

      9
      Indiana Pacers

      10
      Philadelphia 76ers

      11
      Toronto Raptors

      12
      Washington Wizards

      13
      Detroit Pistons

      14
      Charlotte Hornets

## `=` 是完全相同，其他的比較運算符尚有

- `!=`: 不等於
- `>`, `>=`: 大於、大於等於
- `<`, `<=`: 小於、小於等於
- `BETWEEN`: 介於一個範圍
- `IN`: 屬於集合中的值
- `LIKE`: 模糊比對
- `NOT`: 非

```python
# 不等於
sql_query = """
SELECT fullName
  FROM teams
 WHERE confName != 'East';
"""
pd.read_sql(sql_query, conn_nba)
```

      fullName

      0
      New Orleans Pelicans

      1
      Dallas Mavericks

      2
      Denver Nuggets

      3
      Golden State Warriors

      4
      Houston Rockets

      5
      LA Clippers

      6
      Los Angeles Lakers

      7
      Minnesota Timberwolves

      8
      Phoenix Suns

      9
      Portland Trail Blazers

      10
      Sacramento Kings

      11
      San Antonio Spurs

      12
      Oklahoma City Thunder

      13
      Utah Jazz

      14
      Memphis Grizzlies

```python
# 大於等於
sql_query = """
SELECT personId,
       ppg
  FROM careerSummaries
 WHERE ppg >= 25;
"""
pd.read_sql(sql_query, conn_nba)
```

      personId
      ppg

      0
      2544
      27.1

      1
      201142
      27.0

      2
      201935
      25.1

```python
# 介於一個範圍
sql_query = """
SELECT personId,
       ppg
  FROM careerSummaries
 WHERE ppg >= 20 AND
       ppg <= 25;
"""
pd.read_sql(sql_query, conn_nba)
```

      personId
      ppg

      0
      2546
      23.6

      1
      201566
      23.2

      2
      201933
      21.7

      3
      201939
      23.5

      4
      201942
      20.0

      5
      202681
      22.4

      6
      202689
      20.0

      7
      203076
      24.0

      8
      203078
      21.0

      9
      203081
      24.0

      10
      203507
      20.0

      11
      203954
      24.1

      12
      1626157
      22.7

      13
      1626164
      22.3

      14
      1628378
      22.7

      15
      1629027
      23.6

      16
      1629029
      24.4

      17
      1629627
      23.6

```python
# 屬於集合中的值
sql_query = """
SELECT fullName
  FROM teams
 WHERE divName IN ('Atlantic', 'Pacific');
"""
pd.read_sql(sql_query, conn_nba)
```

      fullName

      0
      Boston Celtics

      1
      Golden State Warriors

      2
      LA Clippers

      3
      Los Angeles Lakers

      4
      Brooklyn Nets

      5
      New York Knicks

      6
      Philadelphia 76ers

      7
      Phoenix Suns

      8
      Sacramento Kings

      9
      Toronto Raptors

```python
# 模糊比對 %
sql_query = """
SELECT firstName,
       lastName
  FROM players
 WHERE firstName LIKE 'L%';
"""
pd.read_sql(sql_query, conn_nba)
```

      firstName
      lastName

      0
      LeBron
      James

      1
      Lou
      Williams

      2
      LaMarcus
      Aldridge

      3
      Langston
      Galloway

      4
      Larry
      Nance Jr.

      5
      Lonzo
      Ball

      6
      Lauri
      Markkanen

      7
      Luke
      Kennard

      8
      Luke
      Kornet

      9
      Landry
      Shamet

      10
      Lonnie
      Walker IV

      11
      Luka
      Doncic

      12
      Luguentz
      Dort

      13
      Louis
      King

      14
      Luka
      Samanic

```python
# 模糊比對 _
sql_query = """
SELECT firstName,
       lastName
  FROM players
 WHERE firstName LIKE 'L___';
"""
pd.read_sql(sql_query, conn_nba)
```

      firstName
      lastName

      0
      Luke
      Kennard

      1
      Luke
      Kornet

      2
      Luka
      Doncic

      3
      Luka
      Samanic

```python
# 非
sql_query = """
SELECT fullName
  FROM teams
 WHERE divName NOT IN ('Atlantic', 'Pacific');
"""
pd.read_sql(sql_query, conn_nba)
```

      fullName

      0
      Atlanta Hawks

      1
      Cleveland Cavaliers

      2
      New Orleans Pelicans

      3
      Chicago Bulls

      4
      Dallas Mavericks

      5
      Denver Nuggets

      6
      Houston Rockets

      7
      Miami Heat

      8
      Milwaukee Bucks

      9
      Minnesota Timberwolves

      10
      Orlando Magic

      11
      Indiana Pacers

      12
      Portland Trail Blazers

      13
      San Antonio Spurs

      14
      Oklahoma City Thunder

      15
      Utah Jazz

      16
      Memphis Grizzlies

      17
      Washington Wizards

      18
      Detroit Pistons

      19
      Charlotte Hornets

## 以 `AND` 與 `OR` 結合 `WHERE` 條件

- 以 `AND` 交集兩個以上的條件
- 以 `OR` 聯集兩個以上的條件

```python
sql_query = """
SELECT firstName,
       lastName
  FROM players
 WHERE firstName LIKE 'L%' AND
       lastName LIKE 'J%';
"""
pd.read_sql(sql_query, conn_nba)
```

      firstName
      lastName

      0
      LeBron
      James

```python
sql_query = """
SELECT firstName,
       lastName
  FROM players
 WHERE firstName LIKE 'L%' OR
       lastName LIKE 'J%';
"""
pd.read_sql(sql_query, conn_nba)
```

      firstName
      lastName

      0
      LeBron
      James

      1
      Lou
      Williams

      2
      LaMarcus
      Aldridge

      3
      DeAndre
      Jordan

      4
      James
      Johnson

      5
      Reggie
      Jackson

      6
      Cory
      Joseph

      7
      Nikola
      Jokic

      8
      Tyler
      Johnson

      9
      Langston
      Galloway

      10
      Tyus
      Jones

      11
      Stanley
      Johnson

      12
      Larry
      Nance Jr.

      13
      Damian
      Jones

      14
      Derrick
      Jones Jr.

      15
      Lonzo
      Ball

      16
      Josh
      Jackson

      17
      Lauri
      Markkanen

      18
      Luke
      Kennard

      19
      Justin
      Jackson

      20
      Frank
      Jackson

      21
      Luke
      Kornet

      22
      Jaren
      Jackson Jr.

      23
      Alize
      Johnson

      24
      Landry
      Shamet

      25
      Lonnie
      Walker IV

      26
      Luka
      Doncic

      27
      BJ
      Johnson

      28
      DaQuan
      Jeffries

      29
      Keldon
      Johnson

      30
      Luguentz
      Dort

      31
      Ty
      Jerome

      32
      Cameron
      Johnson

      33
      Louis
      King

      34
      Luka
      Samanic

      35
      Justin
      James

## 這是目前涵蓋的查詢保留字

使用 SQL 語法時，保留字順序必須要遵守。

```sql
SELECT DISTINCT CAST(column_name AS data_type) AS alias_name
  FROM table_name
 WHERE conditions
 ORDER BY column_name DESC
 LIMIT n_obs;
```

## 隨堂練習

[基本查詢：隨堂練習](https://mybinder.org/v2/gh/yaojenkuo/introduction-to-sql/master?filepath=02-exercises.ipynb)

## 隨堂練習：以 `||`  運算符將 `presidential2020` 表格中 `county`、`town` 與 `village` 連結為一個新的欄位並命名為 `combined_key`，再以 `DISTINCT` 暸解台灣獨一的選舉區有哪些

```python
expected_output = pd.read_sql(etq('0201'), conn_twelection)
```

```python
expected_output
```

      combined_key

      0
      南投縣中寮鄉中寮村

      1
      南投縣中寮鄉內城村

      2
      南投縣中寮鄉八仙村

      3
      南投縣中寮鄉和興村

      4
      南投縣中寮鄉崁頂村

      ...
      ...

      7732
      高雄市鼓山區鼓岩里

      7733
      高雄市鼓山區鼓峰里

      7734
      高雄市鼓山區龍井里

      7735
      高雄市鼓山區龍子里

      7736
      高雄市鼓山區龍水里

7737 rows × 1 columns

## 隨堂練習：計算 NBA 球員的身體質量指數（BMI）並由大到小排序，選擇 `firstName`、`lastName` 與 `bmi` 這三個變數

```python
expected_output = pd.read_sql(etq('0202'), conn_nba)
```

```python
expected_output
```

      firstName
      lastName
      bmi

      0
      Zion
      Williamson
      32.853790

      1
      Jaylen
      Adams
      30.487623

      2
      Jarrell
      Brantley
      29.518950

      3
      Eric
      Paschall
      29.512295

      4
      Andre
      Drummond
      29.262204

      ...
      ...
      ...
      ...

      499
      Kostas
      Antetokounmpo
      20.964312

      500
      Justin
      Holiday
      20.814203

      501
      Patrick
      McCaw
      20.321279

      502
      Corey
      Brewer
      20.100858

      503
      Isaac
      Bonga
      19.801500

504 rows × 3 columns

## 隨堂練習：使用 `WHERE` 將 `presidential2020` 中臺北市的資料篩選出來

```python
expected_output = pd.read_sql(etq('0203'), conn_twelection)
```

```python
expected_output
```

      county
      town
      village
      office
      number
      candidates
      votes

      0
      臺北市
      中山區
      下埤里
      524
      1
      宋楚瑜/余湘
      48

      1
      臺北市
      中山區
      下埤里
      524
      2
      韓國瑜/張善政
      377

      2
      臺北市
      中山區
      下埤里
      524
      3
      蔡英文/賴清德
      581

      3
      臺北市
      中山區
      下埤里
      525
      1
      宋楚瑜/余湘
      53

      4
      臺北市
      中山區
      下埤里
      525
      2
      韓國瑜/張善政
      342

      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...

      5179
      臺北市
      萬華區
      騰雲里
      1032
      2
      韓國瑜/張善政
      528

      5180
      臺北市
      萬華區
      騰雲里
      1032
      3
      蔡英文/賴清德
      456

      5181
      臺北市
      萬華區
      騰雲里
      1033
      1
      宋楚瑜/余湘
      43

      5182
      臺北市
      萬華區
      騰雲里
      1033
      2
      韓國瑜/張善政
      502

      5183
      臺北市
      萬華區
      騰雲里
      1033
      3
      蔡英文/賴清德
      512

5184 rows × 7 columns

## 隨堂練習：使用 `WHERE` 將 `presidential2020` 表格中的六都（臺北市、新北市、桃園市、臺中市、臺南市與高雄市）的資料篩選出來

```python
expected_output = pd.read_sql(etq('0204'), conn_twelection)
```

```python
expected_output
```

      county
      town
      village
      office
      number
      candidates
      votes

      0
      新北市
      三峽區
      三峽里
      2010
      1
      宋楚瑜/余湘
      11

      1
      新北市
      三峽區
      三峽里
      2010
      2
      韓國瑜/張善政
      83

      2
      新北市
      三峽區
      三峽里
      2010
      3
      蔡英文/賴清德
      124

      3
      新北市
      三峽區
      中埔里
      2014
      1
      宋楚瑜/余湘
      51

      4
      新北市
      三峽區
      中埔里
      2014
      2
      韓國瑜/張善政
      364

      ...
      ...
      ...
      ...
      ...
      ...
      ...
      ...

      32668
      高雄市
      鼓山區
      龍水里
      1268
      2
      韓國瑜/張善政
      477

      32669
      高雄市
      鼓山區
      龍水里
      1268
      3
      蔡英文/賴清德
      647

      32670
      高雄市
      鼓山區
      龍水里
      1269
      1
      宋楚瑜/余湘
      39

      32671
      高雄市
      鼓山區
      龍水里
      1269
      2
      韓國瑜/張善政
      520

      32672
      高雄市
      鼓山區
      龍水里
      1269
      3
      蔡英文/賴清德
      673

32673 rows × 7 columns

## 隨堂練習：查詢 `careerSummaries` 生涯場均得分 `ppg` 超過 20 分的球員 ID `personId`、場均得分 `ppg`

```python
expected_output = pd.read_sql(etq('0205'), conn_nba)
```

```python
expected_output
```

      personId
      ppg

      0
      2544
      27.1

      1
      2546
      23.6

      2
      201142
      27.0

      3
      201566
      23.2

      4
      201933
      21.7

      5
      201935
      25.1

      6
      201939
      23.5

      7
      202681
      22.4

      8
      203076
      24.0

      9
      203078
      21.0

      10
      203081
      24.0

      11
      203954
      24.1

      12
      1626157
      22.7

      13
      1626164
      22.3

      14
      1628378
      22.7

      15
      1629027
      23.6

      16
      1629029
      24.4

      17
      1629627
      23.6

## 隨堂練習：從 `careerSummaries` 中找出生涯助攻失誤比（assists/turnovers）最高的前 10 個球員 ID `personId`、助攻失誤比 `ast_to_ratio`

\begin{equation}
ast\_to\_ratio = \frac{assists}{turnovers}
\end{equation}

```python
expected_output = pd.read_sql(etq('0206'), conn_nba)
```

```python
expected_output
```

      personId
      ast_to_ratio

      0
      1629669
      6.333333

      1
      1628420
      5.448980

      2
      1626145
      4.775862

      3
      1629162
      4.032258

      4
      1629648
      4.000000

      5
      101108
      3.935682

      6
      1627853
      3.539823

      7
      1629723
      3.500000

      8
      1627832
      3.209964

      9
      202397
      3.071053

## 隨堂練習參考解答

[基本查詢：隨堂練習參考解答](https://mybinder.org/v2/gh/yaojenkuo/introduction-to-sql/master?filepath=02-suggested-answers.ipynb)