Syntax

是否有任何 SQL 方言允許 SELECT 子句的邏輯順序?

  • August 19, 2021

SELECT在 ISO/IEC 標準中,SQL 為子條款規定了以下語法順序:

SELECT
   projection-expressions
FROM
   sources
WHERE
   predicate-expression
GROUP BY
   key-expression
HAVING
   predicate-expression
ORDER BY
   ordering-expressions

雖然邏輯執行順序是這樣的:

FROM
   sources
WHERE
   predicate-expression
GROUP BY
   value-expression
HAVING
   value-expression
SELECT
   projection-expressions
ORDER BY
   ordering-expressions

對於 SQL 的新手使用者來說,即使首先聲明了子句中定義的投影,在or子句SELECT中也不可用,這會令人驚訝——因為電腦程序通常遵循自上而下的執行順序。WHERE``GROUP BY

同樣令人驚訝的是,SQL 作者需要在 、 和 子句中重複他們的表達式SELECTWHERE或者GROUP BY使用不適合簡潔查詢的子查詢。至少當使用者熟悉實際的子句執行順序時,他們知道為什麼需要重複自己,但這並不能阻止它令人沮喪。

我發現的這篇文章記錄了這個問題和其他相關問題:https ://blog.jooq.org/a-beginners-guide-to-the-true-order-of-sql-operations/這並不奇怪StackOverflow 上的 QA 有近 30,000 次瀏覽:https ://stackoverflow.com/questions/3241352/using-an-alias-column-in-the-where-clause-in-postgresql

這讓我想知道是否有任何 SQL 實現允許這種更“合乎邏輯”的子句排序。我注意到 .NET 中的 Linq 實際上確實遵循此順序,儘管我不會將其描述為真正的 SQL 實現,但實際上,在 Linq 中等效的是:

source // FROM equivalent
   .Where( predicate-expression )
   .GroupBy( key-expression )
   .Where( predicate-expression ) // HAVING equivalent
   .Select( projection-expression )
   .OrderBy( ordering-expression )

(我也喜歡 Linq 如何讓您Select()在命令序列中的任何位置添加投影,這樣您就可以使用評估的表達式而無需再次呼叫表達式)。

那麼,是否有任何 SQL 實現可以讓您以更合乎邏輯的結構表達查詢?

SQL的實現

不,SQL 是標準化的。標準的實現沒有太大的不同。那是違背目的的。關係演算(SQL 假裝是)與關係代數方法之間一直存在/一直存在爭執。這是一個古老的辯論,

為數據選擇模型後,下一步是選擇查詢語言。關係數據庫的兩個高級數據子語言系列基於關係代數(源自集合代數)或關係演算

$$ Codd, 197lb , 1971c and Date , 1975 $$(源自謂詞演算)。科德$$ 1971c $$和日期$$ 1975 $$比較了這兩者,發現關係演算更勝一籌,特別是用作自然語言系統的目標語言。他們選擇關係演算作為目標語言的主要原因是演算是非程序性的。即,關係演算中的查詢幾乎沒有傳達有關如何繼續搜尋數據庫的資訊。關係代數更加程序化,這使得自然語言系統自動建構查詢更加困難。-基於關係演算的查詢語言的實現 1970

而且,再次從科德本人那裡,

在關係模型發展的早期(1969-1972),我發明了兩種處理關係的語言:一種本質上是代數的,另一種是基於一階謂詞邏輯的

$$ Codd 1971a $$. 然後我證明了兩種語言具有同等的表達能力$$ Codd 1971d $$,但表明基於邏輯的語言將更可優化(假設未嘗試流跟踪)並且更容易用作 DBMS 之上的推理軟體的介面。- Codd 1990,數據庫管理的關係模型第 2 版

這兩種方法肯定有大量的實現。也就是說,SQL 作為一種實現在微積分方法上是相當固定的。

LINQ 問題

這些問題從未真正用代數方法消失,例如來自這個部落格, .

context.Cars
 .OrderBy(x => x.Id)
 .Skip(50000)
 .Take(1000)
 .ToList();

需要手動優化,

context.Cars
   .Where(x => context.Cars
       .OrderBy(y => y.Id)
       .Select(y => y.Id)
       .Skip(50000)
       .Take(1000)
       .Contains(x.Id)
   )
   .ToList();

如果您有多個具有不同性能特徵(索引,其中大部分被實現為間接和抽象)和統計資訊的不同關係,那麼很難編寫有效工作的過程集邏輯。

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