2012-05-03 36 views
4

以下兩個SQL語句是否總是會生成相同的結果集?在sqlite SQL語句中使用限制與order by子句結合使用

1. SELECT * FROM MyTable where Status='0' order by StartTime asc limit 10 

2. SELECT * FROM (SELECT * FROM MyTable where Status='0' order by StartTime asc) limit 10 
+0

此問題是專門爲SQLite? –

+0

這個問題主要針對SQLite。但是如果一個答案也告訴我有關在同一場景中使用Oracle rownum的一些情況,我會很感激。 – nabulke

回答

5

。首先因爲StartTime列可能沒有UNIQUE約束。所以,即使第一個查詢可能並不總是產生相同的結果 - 本身!

其次,即使沒有兩行具有相同的StartTime,答案仍然是否定

第一條語句總是按照StartTime的順序排列併產生前10行。第二個查詢可能會產生相同的結果集,但只能使用基本優化器,但不能理解子查詢中的ORDER BY是多餘的。只有當執行計劃包含此訂購階段時。 SQLite查詢優化器可能(目前)不是非常明亮,只是這樣做(不知道真的,我們將不得不檢查SQLite *的源代碼)。所以,看起來這兩個查詢總是產生相同的結果。不過,依靠它並不是一個好主意。你永遠不會知道未來版本的SQLite會有哪些變化。

我認爲這是不使用LIMIT沒有ORDER BY,在任何DBMS好的做法。它現在可能工作,但你永遠不知道這些查詢將被應用程序使用多久。當SQLite升級或DBMS更改時,您可能不在身邊。 (*)@ Gareth的鏈接提供了執行計劃,它表明當前SQLite代碼足夠愚蠢以執行冗餘排序。

+1

我和原始優化器一樣,不明白爲什麼第二個查詢中的'order by'是多餘的。你能解釋一下嗎? – nabulke

+0

像那樣的子查詢返回(派生)表。表(基表,視圖或派生表)沒有隱式順序。一些DBMS甚至不允許在派生子查詢和/或視圖中使用ORDER BY。 –

+0

我發佈了一個[後續問題](http://stackoverflow.com/q/10430762/220636)關於oracle和rownum的使用。 – nabulke

6

是的,但訂貨子查詢可能是一個壞習慣進入。您可以在第二個示例中可行地在子查詢外添加更多ORDER BY,例如在外部查詢再次對它們進行排序之前

SELECT * 
FROM (SELECT * 
     FROM Test 
     ORDER BY ID ASC 
    ) AS A 
ORDER BY ID DESC 
LIMIT 10; 

SQLite的仍然執行在內部查詢ORDER BY。不必要的浪費資源。

我已經完成了一個SQL Fiddle來演示,以便您可以查看每個的執行計劃。

+0

+1表示SQLite實際執行此操作的執行計劃。 –