SQL語法 - CTE 一般資料表運算式(COMMON TABLE EXPRESSION)

閱讀時間約 6 分鐘

※ CTE是什麼?

在 SQL 中,我們經常需要從多個表中提取數據,因此會使用子查詢 (subquery)。為了讓子查詢更易讀並實現遞迴查詢,我們可以使用 Common Table Expression (CTE)。

CTE 是一個「暫存」且「具名」的結果集合,透過 AS 關鍵字將查詢結果暫時儲存。CTE 的主要用途有兩個:

  1. 簡化子查詢:讓查詢更易讀和維護。
  2. 遞迴查詢:用於處理層次結構數據或需要遞迴的情況。

簡單來說,CTE 幫助我們將複雜的查詢分解成更易於理解的部分,並且可以用來進行遞迴查詢,使得 SQL 查詢更簡潔和高效。

※ 語法

WITH cte_name AS (
SELECT column1, column2
FROM table_name
WHERE condition
)
SELECT column1, column2
FROM cte_name
WHERE another_condition;

語法解析:

  1. 定義 CTE:
    • 使用 WITH cte_name AS 開頭,給 CTE 一個名字(這裡是 cte_name)。
    • 在括號內寫一個查詢,這個查詢會生成一個臨時的結果集。
  2. 使用 CTE:
  • 在主查詢中,使用剛剛定義的 CTE 名字(cte_name)來引用這個臨時結果集。
  • 主查詢可以對這個臨時結果集進行進一步的查詢和篩選。

※ 解析順序

raw-image
  1. 宣告CTEs:首先,你會宣告一個或多個CTEs,每個CTE包含一個查詢語句(例如SELECT、INSERT、UPDATE、DELETE、CREATE等)。
  2. 使用CTEs:在宣告的CTE之後,你可以在後續的CTE或最終的查詢語句中使用這些CTEs。
  3. 依序解析:解析順序是依照CTE宣告的順序進行的。也就是說,第一個CTE會先被解析,然後是第二個,依此類推。
  4. 最終查詢:在所有CTE宣告完成後,你可以撰寫最終的查詢語句(例如SELECT、INSERT、UPDATE、DELETE、CREATE等),並且可以在這些查詢中使用之前宣告的所有CTEs。

這樣的解析順序確保了每個CTE都可以在後續的CTE或最終查詢中被引用和使用。

※ 實例- 找到最多歌單的使⽤者資訊

-- 宣告CTE來計算每個使用者的歌單數量
WITH UserPlaylistCount AS (
SELECT user_id, COUNT(*) AS playlist_count
FROM playlists
GROUP BY user_id
)

-- 使用CTE來找到擁有最多歌單的使用者
SELECT u.*
FROM users u
JOIN UserPlaylistCount upc ON u.id = upc.user_id
WHERE upc.playlist_count = (
SELECT MAX(playlist_count)
FROM UserPlaylistCount
);

解析順序如下:

  1. 宣告CTE:UserPlaylistCount 計算每個使用者的歌單數量。
  • SELECT user_id, COUNT(*) AS playlist_count:選擇 user_id 並計算每個 user_id 對應的歌單數量,並將這個計數命名為 playlist_count
  • FROM playlists:從 playlists 表格中檢索數據。
  • GROUP BY user_id:根據 user_id 進行分組,以計算每個使用者的歌單數量。

2. 使用CTE來找到擁有最多歌單的使用者

  • SELECT u.*:選擇 users 表格中的所有欄位。
  • FROM users u:從 users 表格中檢索數據,並將其命名為 u
  • JOIN UserPlaylistCount upc ON u.id = upc.user_id:將 users 表格與 UserPlaylistCount CTE 進行連接,條件是 users 表格中的 id 與 UserPlaylistCount CTE 中的 user_id 相等。
  • WHERE upc.playlist_count = (SELECT MAX(playlist_count) FROM UserPlaylistCount):篩選出擁有最多歌單的使用者。這裡使用了一個子查詢來找到 UserPlaylistCount CTE 中的最大 playlist_count,並將其與 upc.playlist_count 進行比較。

總結

這段SQL語句的目的是找到擁有最多歌單的使用者。首先,使用CTE計算每個使用者的歌單數量,然後在最終查詢中使用這個CTE來找到擁有最多歌單的使用者。

※ 與 Subquery 的比較

CTE(Common Table Expressions)

優點

  1. 可讀性高CTE可以將複雜的查詢分解成多個部分,使查詢更易於理解和維護。
  2. 子任務的邏輯清楚地分開CTE允許你將子任務查詢邏輯分成多個部分,這樣在解決問題時,可以更清晰地思考每個步驟。
  3. 減少重複:CTE可以在同一查詢中多次引用,避免重複代碼。
  4. 遞迴查詢:CTE支持遞迴查詢,這在處理層次結構數據時非常有用。

缺點:

  1. 性能:在某些情況下,CTE可能會比子查詢慢,特別是當CTE被多次引用時。
  2. 範圍限制:CTE的作用範圍僅限於它所屬的查詢塊,不能在其他查詢中重用。

子查詢(Subqueries)

優點:

  1. 靈活性:子查詢可以嵌套在SELECT、INSERT、UPDATE、DELETE等語句中,提供了很大的靈活性。
  2. 性能:在某些情況下,子查詢可能比CTE更快,特別是當子查詢只執行一次時。

缺點:

  1. 可讀性差:嵌套的子查詢可能會使查詢變得複雜且難以理解。
  2. 重用性差:子查詢通常不能在同一查詢中多次引用,這可能導致代碼重複。
  3. 調試困難:由於子查詢嵌套在主查詢中,調試和維護可能會變得更加困難。

總結

  • CTE 更適合用於需要高可讀性和邏輯分離的複雜查詢。
  • 子查詢 更適合用於需要靈活性和可能具有性能優勢的簡單查詢。



    全端網頁開發專業知識分享
    留言0
    查看全部
    發表第一個留言支持創作者!
    ※ 為什麼需要 Subquery? 當⼀個任務需要多個 Query 完成任務,可以使⽤ Subquery 把多個 Query 合併成⼀個 Query。 當我們在進行SQL查詢時,每次查詢都需要在Web Server和資料庫之間來回傳遞資料。這個過程會產生網路延遲,特別是當兩者之間的物理距離較遠時
    ※ 何時該使用 JOIN? JOIN 使用的時機是:當你需要同時查詢一張以上的資料表的時候。 ※ SQL有哪些TABLE JOIN的方式? INNER JOIN LEFT JOIN RIGHT JOIN SELF JOIN ※ 使用 JOIN 的時候,我們需要考慮到: 我要使用哪一種
    ※ 別名: 目的在於提高SQL查詢的可讀性和簡潔性。 ※ 別名有兩種: Column Alias(列別名):在查詢結果中的某一列,取一個臨時的新名字。 Table Alias(表別名):給查詢中的表取一個短暫的新名字。 ※ Column Alias ※ 為什麼需要 Column A
    ※ GROUP BY 用於將數據表中的數據按照一個或多個列進行分組。例如在處理一個表格的資料時,可以指定欄位,一個或是多個,然後把將其視為ID進行分組處理。 ※ 語法 SELECT column1, column2, ..., aggregate_function(column) FROM
    ※ 什麼是WHERE? 使用 WHERE來設定條件,可以幫助我們縮小查詢結果的範圍,取得想要的結果。 ※ 語法: ※ 解析順序: From:先看是哪一張table→table裡面符合Where指定條件的record→再看Select指定的是那些欄位→再根據那個欄位進行排序。 ※ 使⽤⽅
    ※ 什麼是ORDER BY? 可以讓SELECT出來的結果,根據你想要的方式排序。簡單說,用於對查詢結果進行排序。 ※ 語法: SELECT select_list FROM table_name ORDER BY column1 [ASC|DESC], column2 [ASC|DESC]
    ※ 為什麼需要 Subquery? 當⼀個任務需要多個 Query 完成任務,可以使⽤ Subquery 把多個 Query 合併成⼀個 Query。 當我們在進行SQL查詢時,每次查詢都需要在Web Server和資料庫之間來回傳遞資料。這個過程會產生網路延遲,特別是當兩者之間的物理距離較遠時
    ※ 何時該使用 JOIN? JOIN 使用的時機是:當你需要同時查詢一張以上的資料表的時候。 ※ SQL有哪些TABLE JOIN的方式? INNER JOIN LEFT JOIN RIGHT JOIN SELF JOIN ※ 使用 JOIN 的時候,我們需要考慮到: 我要使用哪一種
    ※ 別名: 目的在於提高SQL查詢的可讀性和簡潔性。 ※ 別名有兩種: Column Alias(列別名):在查詢結果中的某一列,取一個臨時的新名字。 Table Alias(表別名):給查詢中的表取一個短暫的新名字。 ※ Column Alias ※ 為什麼需要 Column A
    ※ GROUP BY 用於將數據表中的數據按照一個或多個列進行分組。例如在處理一個表格的資料時,可以指定欄位,一個或是多個,然後把將其視為ID進行分組處理。 ※ 語法 SELECT column1, column2, ..., aggregate_function(column) FROM
    ※ 什麼是WHERE? 使用 WHERE來設定條件,可以幫助我們縮小查詢結果的範圍,取得想要的結果。 ※ 語法: ※ 解析順序: From:先看是哪一張table→table裡面符合Where指定條件的record→再看Select指定的是那些欄位→再根據那個欄位進行排序。 ※ 使⽤⽅
    ※ 什麼是ORDER BY? 可以讓SELECT出來的結果,根據你想要的方式排序。簡單說,用於對查詢結果進行排序。 ※ 語法: SELECT select_list FROM table_name ORDER BY column1 [ASC|DESC], column2 [ASC|DESC]
    你可能也想看
    Google News 追蹤
    Thumbnail
    這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
    Thumbnail
    美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
    Thumbnail
    Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
    Thumbnail
    在工作情境中手動執行SQL語法更新中文字時,有時會遇到中文字顯示問號(?)的情況。這篇文章將介紹如何解決手動執行SQL語法時造成中文顯示問號(?)的方法。
    Thumbnail
    題目敘述 題目會給我們兩張資料表,第一張是Sales,第二張是Product。 第一張是Sales表格,裡面分別有sale_id、 product_id、year、quantity、price等欄位。其中(sale_id、 product_id)做為複合主鍵Primary key Table:
    Thumbnail
    題目敘述 題目會給我們兩張資料表。 第一張資料表是Employees 裡面分別有id、name等欄位。這張資料表的id是主鍵。 第二張資料表是EmployeeUNI 裡面分別有id、unique_id等欄位。 題目要求我們列出每位員工對應到的Unique ID
    Thumbnail
    題目敘述 題目會給我們一張Views資料表。裡面分別有article_id、author_id、viewer_id、view_date等欄位。題目說這張資料表沒有主鍵Primary key,而且可能有重複欄位。 題目要求我們列出所有讀過自己寫的文章的作者ID 輸出答案時,請以作者ID做升序排列
    Thumbnail
    題目敘述 題目會給我們一張Products資料表。裡面分別有product_id、new_price、change_date等欄位。其中(product_id, change_date)是這張資料表的複合主鍵Primary key。 所有商品預設都是10元。之後若有更新,則以新價格為主。 要求
    Thumbnail
    題目會給我們一張資料表Queue,代表乘客排隊上車的情境。 裡面分別有person_id、 person_name 、weight、turn等欄位,分別代表乘客ID、乘客姓名、乘客重量、乘客排隊的順序。 要求我們判斷,在不超重的條件下,最後一位上車的乘客是誰。
    Thumbnail
    題目敘述 題目會給我們一張Cinema資料表,裡面分別有id、movie、description, rating 等欄位,其中id 是主鍵Primary Key。 要求我們列出所有推薦人ID為奇數,而且不無聊的電影,印出時依照電影rating評分從高到低降序排列。 Table: Cinema
    Thumbnail
    SQL 基本篇 - CRUD、運算子、內建函式
    Thumbnail
    我自己是使用微軟的SQLIT軟體 這個軟體的操作上 沒有辦法直接用滑鼠點選或是拖拉的方式來看到你想看到的表格 都是要下指令的像是要看data.sqlite中的user這個table我就必須下 才能把table調閱出來看 那做為一個python三年工作經驗的工程師通常我不會直接在SQLIT軟體 裡面下
    Thumbnail
    這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
    Thumbnail
    美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
    Thumbnail
    Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
    Thumbnail
    在工作情境中手動執行SQL語法更新中文字時,有時會遇到中文字顯示問號(?)的情況。這篇文章將介紹如何解決手動執行SQL語法時造成中文顯示問號(?)的方法。
    Thumbnail
    題目敘述 題目會給我們兩張資料表,第一張是Sales,第二張是Product。 第一張是Sales表格,裡面分別有sale_id、 product_id、year、quantity、price等欄位。其中(sale_id、 product_id)做為複合主鍵Primary key Table:
    Thumbnail
    題目敘述 題目會給我們兩張資料表。 第一張資料表是Employees 裡面分別有id、name等欄位。這張資料表的id是主鍵。 第二張資料表是EmployeeUNI 裡面分別有id、unique_id等欄位。 題目要求我們列出每位員工對應到的Unique ID
    Thumbnail
    題目敘述 題目會給我們一張Views資料表。裡面分別有article_id、author_id、viewer_id、view_date等欄位。題目說這張資料表沒有主鍵Primary key,而且可能有重複欄位。 題目要求我們列出所有讀過自己寫的文章的作者ID 輸出答案時,請以作者ID做升序排列
    Thumbnail
    題目敘述 題目會給我們一張Products資料表。裡面分別有product_id、new_price、change_date等欄位。其中(product_id, change_date)是這張資料表的複合主鍵Primary key。 所有商品預設都是10元。之後若有更新,則以新價格為主。 要求
    Thumbnail
    題目會給我們一張資料表Queue,代表乘客排隊上車的情境。 裡面分別有person_id、 person_name 、weight、turn等欄位,分別代表乘客ID、乘客姓名、乘客重量、乘客排隊的順序。 要求我們判斷,在不超重的條件下,最後一位上車的乘客是誰。
    Thumbnail
    題目敘述 題目會給我們一張Cinema資料表,裡面分別有id、movie、description, rating 等欄位,其中id 是主鍵Primary Key。 要求我們列出所有推薦人ID為奇數,而且不無聊的電影,印出時依照電影rating評分從高到低降序排列。 Table: Cinema
    Thumbnail
    SQL 基本篇 - CRUD、運算子、內建函式
    Thumbnail
    我自己是使用微軟的SQLIT軟體 這個軟體的操作上 沒有辦法直接用滑鼠點選或是拖拉的方式來看到你想看到的表格 都是要下指令的像是要看data.sqlite中的user這個table我就必須下 才能把table調閱出來看 那做為一個python三年工作經驗的工程師通常我不會直接在SQLIT軟體 裡面下