Sql-Server

Microsoft SQL Server 2014 從交叉應用中的查詢嵌套

  • June 18, 2021

從 OUTER APPLY 語句中的嵌套查詢中進行選擇時,嵌套查詢似乎在某些情況下只被評估一次。

向 Azure 回饋論壇報告的錯誤:https ://feedback.azure.com/forums/908035-sql-server/suggestions/39428632-microsoft-sql-server-2014-incorrect-result-when-s

這是預期的行為,還是我在文件中遺漏了什麼,或者這是 SQL Server 中的錯誤?

此外,是否有可能強制評估每一行的嵌套查詢?

測試案例 1

評估 VALUES 中每一行的嵌套 FROM 查詢(恕我直言預期行為)

SELECT
   v,
   v2
FROM
   (VALUES (1), (2), (3), (4)) AS inner_query(v)
   OUTER APPLY (
       SELECT
           MAX(inner_v2) AS v2
       FROM (
           SELECT 
               15 AS id,
               v AS inner_v2
       ) AS outer_query
       GROUP BY id
   ) AS outer_apply

結果:

| v | v2|
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |

測試案例 2

它還評估 VALUES 中每一行的嵌套 FROM 查詢(恕我直言預期行為)

SELECT
   v,
   v2
FROM
   (VALUES (1), (2), (3), (4)) AS inner_query(v)
   OUTER APPLY (
       SELECT
           MAX(inner_v2) AS v2
       FROM (
           SELECT 
               15 AS id,
               v AS inner_v2
           UNION ALL
           SELECT
               id AS id,
               TestCaseTemp2.v AS inner_v2
           FROM
               (VALUES (1337, 0)) AS TestCaseTemp2(id, v)
           WHERE TestCaseTemp2.v != 0
       ) AS outer_query
       GROUP BY id
   ) AS outer_apply;

結果:

| v | v2|
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |

測試案例 3

只計算一次嵌套的 FROM 查詢

CREATE TABLE TestCaseTemp
(
   id int,
   v int
);
INSERT INTO TestCaseTemp VALUES (1337, 0);

SELECT
   v,
   v2
FROM
   (VALUES (1), (2), (3), (4)) AS inner_query(v)
   OUTER APPLY (
       SELECT
           MAX(inner_v2) AS v2
       FROM (
           SELECT 
               15 AS id,
               v AS inner_v2
           UNION ALL
           SELECT
               id AS id,
               TestCaseTemp.v AS inner_v2
           FROM
               TestCaseTemp
           WHERE TestCaseTemp.v != 0
       ) AS outer_query
       GROUP BY id
   ) AS outer_apply;

DROP TABLE TestCaseTemp;

結果:

| v | v2|
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |

這是 SQL Server 中的錯誤嗎?

是的,當然,1最終結果中所有行中返回的 僅存在於外部輸入的第一行中,因此甚至不應該在後續行的範圍內。它看起來與 Paul White在這裡詳細討論的基本問題相同。

我在 dbfiddle (SQL Server 2019) 中執行了您的最終查詢並在此處粘貼了計劃https://www.brentozar.com/pastetheplan/?id=Sy4sBB5lI 看起來排序執行了 4 次(每個外行一次)但是對於出於某種原因,它會倒帶而不是重新綁定,因此不會多次呼叫該排序的子運算符。這是一個錯誤,因為對外部連接 ( ) 的相關參數的引用Union1004應該會在其值更改時導致重新綁定。因此,Union1004從未重新評估計劃節點 5 中的引用。

我看到你現在在這里報告了它https://feedback.azure.com/forums/908035-sql-server/suggestions/39428632-microsoft-sql-server-2014-incorrect-result-when-s

是否有可能強制評估每一行的嵌套查詢?

添加查詢提示OPTION (MERGE UNION)適用於您的範例,我不知道這是否足以在所有情況下避免該錯誤,但從連結的 Paul White 答案看來它應該可以工作。在您的範例中,它的工作原理是排序在計劃中被向下推,因此它只會倒回TestCaseTemp行,而不是整個聯合結果。您還可以添加適當的索引以完全刪除排序。

引用自:https://dba.stackexchange.com/questions/257326