是否有任何 SQL 方言允許 SELECT 子句的邏輯順序?
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 作者需要在 、 和 子句中重複他們的表達式
SELECT
,WHERE
或者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();
如果您有多個具有不同性能特徵(索引,其中大部分被實現為間接和抽象)和統計資訊的不同關係,那麼很難編寫有效工作的過程集邏輯。