關聯子查詢是一種特殊的子查詢,子查詢的執行依賴外部查詢的當前行。關聯子查詢的外部查詢每查詢一行數據,子查詢都需要運行一次,在數據量大的情況下,可能會導致查詢性能下降。本文主要介紹關聯子查詢的用法及常見報錯。
前提條件
集群內核版本需為3.1.9.0及以上版本。
說明 如何查看集群內核版本,請參見如何查看實例版本信息。如需升級內核版本,請聯系技術支持。
使用限制
關聯列的限制
說明
關聯列是指子查詢中包含的來自外部查詢的列。
關聯列僅允許出現在子查詢的WHERE子句中。
關聯子查詢不支持跳層關聯,即不支持在子查詢包含的子查詢中出現關聯列。例如:
SELECT * FROM ts1 WHERE ts1.a > (SELECT MAX(ts3.c) FROM ts3 WHERE ts3.c IN (SELECT ts2.a FROM ts2 WHERE ts1.b = ts2.b ) );
子查詢的限制
子查詢不能位于JOIN語句中。
子查詢中不能包含任意窗口函數。
子查詢不能包含任何的集合操作。例如UNION等。例如:
SELECT * FROM ts1 WHERE ts1.a IN (SELECT ts2.a FROM ts2 WHERE ts1.b = ts2.b UNION SELECT ts3.a FROM ts3 );
IN條件的子查詢不能包含LIMIT、GROUP BY、ORDER BY、JOIN。例如:
SELECT * FROM ts1 WHERE ts1.a IN (SELECT ts2.a FROM ts2 WHERE ts1.b = ts2.b LIMIT 10);
SELECT * FROM ts1 WHERE ts1.a IN (SELECT AVG(ts2.a) FROM ts2 WHERE ts1.b = ts2.b GROUP BY ts2.c );
示例
使用關聯子查詢,查詢商品的最低折扣:
SELECT id,
(SELECT MIN(discount)
FROM item
WHERE goods.id = goods_id )
FROM goods;
您也可以通過JOIN改寫上述關聯子查詢:
SELECT id,t.min_discount
FROM goods
LEFT JOIN
(SELECT goods_id,
MIN(discount) AS min_discount
FROM item
GROUP BY goods_id ) t
ON t.goods_id = goods.id;
常見報錯
Given correlated subquery with correlation: [column_name] is not supported
原因:關聯列僅允許出現在WHERE子句中。AnalyticDB for MySQL在執行關聯子查詢時,會解關聯,即將關聯子查詢變為普通子查詢,若關聯列出現在子查詢的SELECT子句中,會解關聯失敗,進而導致報錯。
以如下代碼為例,關聯列ts1.a
出現在子查詢的SELECT子句中,導致關聯查詢無法解開,出現報錯。
SELECT ts1.a,
(SELECT SUM(ts2.a) + ts1.a
FROM ts2
WHERE ts1.b = ts2.b )
FROM ts1;
解決方法:
方法一:在子查詢的SELECT子句中去除關聯列,改寫SQL。
SELECT ts1.a, (SELECT SUM(ts2.a) FROM ts2 WHERE ts1.b = ts2.b ) + ts1.a FROM ts1;
方法二:通過JOIN改寫關聯子查詢。
SELECT ts1.a, tt.suma + ts1.a FROM ts1 LEFT JOIN (SELECT ts2.b AS b, SUM(ts2.a) AS suma FROM ts2 GROUP BY ts2.b ) tt ON ts1.b = tt.b;
Scalar sub-query has returned multiple rows
原因:關聯子查詢返回結果有多行時,會出現該報錯,若返回結果行數等于0或1時,不會報錯。
以如下代碼為例,外部查詢的WHERE子句中是等值條件,且子查詢的返回結果為多行,出現報錯。
SELECT ts1.a
FROM ts1
WHERE ts1.a =
(SELECT ts2.a
FROM ts2
WHERE ts1.b = ts2.b );
解決方法:根據SQL語義修改SQL。根據上述查詢中的語義,將外部查詢的等值條件修改為IN條件。
SELECT ts1.a
FROM ts1
WHERE ts1.a IN
(SELECT ts2.a
FROM ts2
WHERE ts1.b = ts2.b );
文檔內容是否對您有幫助?