Navicat 部落格

相互關聯子查詢 2023 年 2 月 2 日,由 Robert Gravelle 撰寫

子查詢可以分為兩類:

  • 非相互關聯(簡單)子查詢獨立於其包含(外部)陳述式獲得其結果。
  • 相互關聯子查詢參考其外部查詢的值以便執行。

當非相互關聯子查詢執行時(獨立於外部查詢),首先執行子查詢,然後將其結果傳遞至外部查詢。與此同時,相互關聯子查詢通常會在執行之前從其外部查詢中獲得值。當子查詢傳回結果時,它將其結果傳遞至外部查詢。

現在我們知道相互關聯子查詢和非相互關聯子查詢有何不同,本文將介紹如何在 Navicat Premium 16 中編寫相互關聯子查詢。

語法和用法

相互關聯子查詢會計算父陳述式處理的每一列一次。父陳述式可以是 SELECT、UPDATE 或 DELETE 陳述式。以下是 SELECT 查詢的語法:

SELECT column1, column2, ....
FROM table1 outer
WHERE column1 operator
  (SELECT column1, column2
   FROM table2
   WHERE expr1 = outer.expr2);

相互關聯子查詢是一種讀取資料表中每一列並將每一列中的值與相關資料比較的方法。只要子查詢必須為主要查詢考慮的每個候選列傳回不同的結果或結果集,就會使用它。換句話說,你可以使用相互關聯子查詢來回答一個多部分問題,其答案取決於父陳述式處理的每一列中的值。

實際範例

這是來自 stackoverflow 的一個相當巧妙的查詢,在 Sakila 範例資料庫提取每個國家或地區觀看次數最多的電影。

第一步是計算每部電影在每個國家或地區的觀看次數。以下是 SELECT 陳述式:

SELECT 
  F.title AS title, 
  CO.country_id AS country_id,
  CO.country AS country_name, 
  count(F.film_id) as times
FROM customer C INNER JOIN address A ON C.address_id = A.address_id
INNER JOIN city CI ON A.city_id = CI.city_id
INNER JOIN country CO ON CI.country_id = CO.country_id
INNER JOIN rental R ON C.customer_id = R.customer_id
INNER JOIN inventory I ON R.inventory_id = I.inventory_id
INNER JOIN film F ON I.film_id = F.film_id
GROUP BY F.film_id, CO.country_id;

以下是 Navicat Premium 16 中的上述查詢和結果:

most viewed film per country inner query (170K)

下一步是將上述結果轉換為國家或地區的清單,連同觀看次數最多的電影名稱和觀看次數。以下是含有互相關聯子查詢的完整查詢,並附有解釋:

most viewed film per country correlated query (159K)

解釋:

  • 子查詢:提取根據國家或地區分組的電影計數清單。
  • GROUP_CONCAT(title ORDER BY times DESC SEPARATOR '|||') 傳回該「列」中的所有標題,觀看次數最多的標題排在第一位。而分隔符號無關緊要,只要不出現在標題中即可。
  • SUBSTRING_INDEX('...', '|||', 1) 提取字串的第一部分,直到找到「|||」為止,在本例中是第一個(因此也是觀看次數最多的)標題。

關於相互關聯子查詢的最後想法

在今天的文章中,我們學習了如何使用 Navicat Premium 16 編寫互相關聯子查詢。預先提醒一下,互相關聯子查詢可能很慢。然而,適當的最佳化可以顯著提高它們的速度。

Navicat 文章
頻道記錄
分享
部落格封存檔