自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

SQL 查詢之公用表表達式(CTE)

數(shù)據(jù)庫 其他數(shù)據(jù)庫
在關(guān)系型數(shù)據(jù)庫中,表示數(shù)據(jù)層級結(jié)構(gòu)的表很常見,例如,上下級關(guān)系、父子組件關(guān)系等。為了在這些層級結(jié)構(gòu)中進行從上到下或從下到上的遍歷,可以使用遞歸 CTE。

CTE 的全稱是 common table expression,即公用表表達式,它可以簡化 SQL 查詢代碼。CTE 是可命名的子查詢,它是在 SQL 查詢執(zhí)行期間臨時創(chuàng)建的,包含列與記錄的虛擬表。CTE 只能被調(diào)用它的主查詢訪問,主查詢執(zhí)行完畢后會被刪除。

CTE 可以簡化查詢語句

CTE的基礎(chǔ)語法如下。

1WITH my_cte AS (
2  SELECT a,b,c
3  FROM T1
4)
5SELECT a,c
6FROM my_cte
7WHERE ....

CTE 語句以 WITH 關(guān)鍵字開始,所以 CTE 又被稱為 WITH 語句。在 WITH 關(guān)鍵字之后是 CTE 的名字;在 AS 關(guān)鍵字之后的括號里寫入要實現(xiàn)的查詢語句。

在上例中,CTE 的名字是 my_cte,查詢語句為 SELECT a,b,c FROM T1。

主查詢在定義 CTE 語句的括號后面。定義 CTE 之后,即可在主查詢中通過 CTE 的名字對其進行引用。主查詢也稱為外部查詢,在這個示例中是 SELECT a,c FROM my_cte WHERE ...。

簡單的 CTE 示例

本文中的例子都基于以下這個 sales 表,這個表模擬了一家連鎖書店的銷售數(shù)據(jù),示例如下。

示例數(shù)據(jù)示例數(shù)據(jù)

生成 sales 表的 SQL 代碼如下。

1-- 創(chuàng)建名為sales的表
 2CREATE TABLE sales (
 3    branch VARCHAR(50),
 4    date DATE,
 5    seller VARCHAR(50),
 6    item VARCHAR(50),
 7    quantity INT,
 8    unit_price DECIMAL(10, 2)
 9);
10
11-- 插入數(shù)據(jù)
12INSERT INTO sales (branch, date, seller, item, quantity, unit_price)
13VALUES
14    ('Beijing-1', '2024-06-07', 'Zhangsan', 'SQL Data Analysis', 1, 80),
15    ('Shanghai-1', '2024-06-06', 'Lisi', 'Python Data Analysis', 2, 120),
16    ('Shanghai-2', '2024-06-07', 'Wangwu', 'Pandas Workshop', 1, 60),
17    ('Beijing-1', '2024-06-07', 'Zhangsan', 'Polars in Action', 1, 50),
18    ('Shanghai-2', '2024-06-07', 'Wangwu', 'Echarts Data Charts', 2, 90),
19    ('Shanghai-1', '2024-06-07', 'Lisi', 'Mastering Pandas', 5, 75),
20    ('Shanghai-1', '2024-06-07', 'Zhaoliu', 'R Projects', 2, 100);

我們先看一個簡單的例子。輸出 sales 表中的原始數(shù)據(jù)記錄,但要在 sales 表中再添加一列,顯示當(dāng)天(date)在同一分店中售出圖書的最高價格。獲取售價最高的圖書價格可以使用如下 CTE。

1WITH highest AS (
 2  SELECT
 3    branch,
 4    date,
 5    MAX(unit_price) AS highest_price
 6  FROM sales
 7  GROUP BY branch, date
 8)
 9SELECT
10  sales.*,
11  h.highest_price
12FROM sales
13JOIN highest h
14  ON sales.branch = h.branch
15    AND sales.date = h.date

上述查詢定義了名為 highest 的 CTE,這個虛擬表包含的列為 branch、date 和highest_price,分別表示分店的名稱、銷售日期和當(dāng)天該分店銷售的最高單價。

然后,在主查詢中,像使用常規(guī)表一樣使用虛擬表 highest。

最后,將 highest 的查詢結(jié)果與 sales 表進行連接。

查詢的結(jié)果如下。

查詢結(jié)果查詢結(jié)果

下面這個例子顯示各分店最高的單日收入。

1WITH daily_revenue AS (
 2  SELECT
 3    branch,
 4    date,
 5    SUM(unit_price * quantity) AS daily_revenue
 6  FROM   sales
 7  WHERE EXTRACT(YEAR FROM date) = 2024
 8  GROUP BY 1,2
 9)
10SELECT
11  branch,
12  MAX(daily_revenue) max_daily_revenue
13FROM daily_revenue
14GROUP BY 1
15ORDER BY 2 DESC

在這段代碼中,首先定義名為 daily_revenue 的 CTE,包含的列為 branch、date 和 daily_revenue,數(shù)據(jù)記錄為每家分店在 2024 年內(nèi)每一天的日銷售額。

然后,在主查詢中,獲取 2024 年每家分店的最高日銷售額。

最后,按max_daily_revenue 降序排列輸出數(shù)據(jù)。

查詢結(jié)果查詢結(jié)果

在 SQL 高級查詢中使用 CTE

主查詢中可以使用多個 CTE。下面的示例中介紹如何使用多個 CTE 對復(fù)雜的 SQL 語句進行簡化。

假設(shè)要顯示某個城市的月銷售額,以及該城市中每個分店的銷售額。

在本例中,先創(chuàng)建兩個 CTE。再在主查詢中把這兩個 CTE 連接起來。

1WITH shanghai1_monthly_revenue AS (
 2  SELECT
 3    EXTRACT(MONTH FROM date) as month,
 4    SUM(unit_price * quantity) AS revenue
 5  FROM sales
 6  WHERE EXTRACT(YEAR FROM date) = 2024
 7    AND branch = 'Shanghai-1'
 8  GROUP BY 1
 9),
10shanghai2_monthly_revenue AS (
11  SELECT
12    EXTRACT(MONTH FROM date) as month,
13    SUM(unit_price * quantity) AS revenue
14  FROM sales
15  WHERE EXTRACT(YEAR FROM date) = 2024
16    AND branch = 'Shanghai-2'
17  GROUP BY 1
18)
19SELECT
20  s1.month,
21  s1.revenue + s2.revenue AS shanghai_revenue,
22  s1.revenue AS shanghai1_revenue,
23  s2.revenue AS shanghai2_revenue
24FROM shanghai1_monthly_revenue s1, shanghai2_monthly_revenue s2
25WHERE s1.month = s2.month

在上述代碼中,定義了 shanghai1_monthly_revenue 與 shanghai2_monthly_revenue 兩個 CTE,使用這兩個 CTE 獲取 2024 年上海各分店的月銷售額。

接下來,使用 month 列連接這兩個 CTE,并把兩個分店的銷售額相加,以獲取上海的總銷售額。

查詢結(jié)果如下。

查詢結(jié)果查詢結(jié)果

下例顯示每家分店最大金額的訂單及該訂單的日期。為此,需要創(chuàng)建一個 CTE,根據(jù)訂單金額為各分店的訂單進行排名(position 列就是排名)。

1WITH tickets AS (
 2  SELECT distinct
 3    branch,
 4    date,
 5    unit_price * quantity AS ticket_amount,
 6    ROW_NUMBER() OVER (
 7      PARTITION BY branch
 8      ORDER by unit_price * quantity DESC
 9    ) AS position
10  FROM sales
11  ORDER BY 3 DESC
12)
13SELECT
14  branch,
15  date,
16  ticket_amount
17FROM tickets
18WHERE position =1

在這段代碼中,創(chuàng)建了名為 tickets 的 CTE,包含 branch、date、titcket_amount和 position。

在主查詢中,過濾 position 等于 1 的記錄,以獲取各分店銷售額最大的訂單。

查詢結(jié)果如下。

查詢結(jié)果查詢結(jié)果

SQL 查詢中的嵌套 CTE

本例介紹如何使用嵌套 CTE。輸出所有單價超過 90 元的圖書,以及上海分店(Shanghai-2)的銷售數(shù)量。

1WITH over_90_items AS (
 2  SELECT DISTINCT
 3    item,
 4    unit_price
 5  FROM sales
 6  WHERE unit_price >=90
 7),
 8shanghai2_over_90 AS (
 9  SELECT
10    o90.item,
11    o90.unit_price,
12    coalesce(SUM(s.quantity), 0) as total_sold
13  FROM over_90_items o90
14  LEFT JOIN sales s
15  ON o90.item = s.item AND s.branch = 'Shanghai-2'
16  GROUP BY o90.item, o90.unit_price
17)
18SELECT item, unit_price, total_sold
19FROM shanghai2_over_90;

over_90_items 用于篩選單價大于或等于 90 元的圖書。

shanghai2_over_90 用于篩選 Shanghai-2 分店售出的超過 90 元的圖書的數(shù)量。

這就是嵌套 CTE 的基本用法。

注意,shanghai2_over_90 中的 FROM 子句中引用了 over_90_items。

使用 LEFT JOIN sales 的原因是 Shanghai-2 分店可能沒有銷售過價格超過 90 元的圖書。

查詢結(jié)果如下。

查詢結(jié)果查詢結(jié)果

遞歸查詢與 CTE

在關(guān)系型數(shù)據(jù)庫中,表示數(shù)據(jù)層級結(jié)構(gòu)的表很常見,例如,上下級關(guān)系、父子組件關(guān)系等。

為了在這些層級結(jié)構(gòu)中進行從上到下或從下到上的遍歷,可以使用遞歸 CTE。

RECURSIVE 是定義遍歷遞歸數(shù)據(jù)結(jié)構(gòu)的 CTE 的關(guān)鍵字。CTE 遞歸查詢的形式如下。

1WITH RECURSIVE  cte_name AS (
2     CTE_query_definition  -- 非遞歸查詢項
3UNION ALL
4     CTE_query_definition  -- 遞歸查詢項
5)
6SELECT * FROM cte_name;

限于本文的篇幅,有 CTE 的遞歸查詢就先不贅述了,關(guān)注我們的公眾號,我會在后續(xù)的文章中進行介紹。

結(jié)語

SQL 的 CTE 非常強大,它可以讓 SQL 查詢代碼更簡潔,邏輯更清晰。

責(zé)任編輯:武曉燕 來源: Python學(xué)研大本營
相關(guān)推薦

2010-11-03 11:55:23

DB2公共表表達式

2010-10-21 10:56:29

SQL Server查

2009-09-10 15:35:07

LINQ查詢表達式

2011-10-28 16:34:13

LINQ

2009-09-17 11:08:55

LINQ查詢表達式

2009-03-23 10:47:43

數(shù)據(jù)庫SQLLINQ

2009-08-27 09:13:28

LINQ查詢表達式

2009-09-07 17:18:33

LINQ查詢表達式

2009-09-11 09:53:16

Linq查詢表達式

2017-05-12 10:47:45

Linux正則表達式程序基礎(chǔ)

2019-12-17 17:01:02

MySQLSQL數(shù)據(jù)庫

2009-09-17 09:09:50

Lambda表達式Linq查詢

2024-10-17 17:03:43

SQL正則表達式MySQL

2014-01-05 17:41:09

PostgreSQL表達式

2024-03-01 08:51:01

Django查詢表達式查詢語句

2009-06-08 16:49:05

Java正則表達式group

2011-08-12 10:31:01

T-SQL查詢基于列的邏輯表達式

2024-10-11 18:36:51

2010-11-12 13:20:31

SQL Server

2022-01-14 07:56:39

C#動態(tài)查詢
點贊
收藏

51CTO技術(shù)棧公眾號