2012-11-16 37 views
11

我在找一些像這樣的expresion(使用SQL Server 2008)返回行的特定範圍之間,有一個select語句

SELECT TOP 10 columName FROM tableName 

但不是我需要在10和20之間的值我想知道是否有隻使用一個SELECT語句的方法。

例如,這是沒有用的:

SELECT columName FROM 
(SELECT ROW_NUMBER() OVER(ORDER BY someId) AS RowNum, * FROM tableName) AS alias 
WHERE RowNum BETWEEN 10 AND 20 

因爲選擇括號內已經返回所有的結果,我希望避免這種情況,由於性能。

回答

0

使用SQL Server 2012獲取/跳過!

SELECT SalesOrderID, SalesOrderDetailID, ProductID, OrderQty, UnitPrice, LineTotal 
FROM AdventureWorks2012.Sales.SalesOrderDetail 
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY; 

沒有比您描述的舊版本的sql server更好的了。也許使用CTE,但不太可能有所作爲。或者,你可以刪除前10行,然後得到下10行,但我加倍任何人會想要做到這一點。

+1

升級到SQL Server 2012通常不是「按住你的手指」選項。而且我認爲*在早期版本的SQL Server中有更好的答案。例如,爲什麼不在應用行號時只檢索* key *值,然後將該輸出(它將會*很* skinner)加入表中? –

+0

@AaronBertrand,你是對的。我完全同意升級並不容易,但是如果OP使用這個聲明很多並且真的關心性能,這是他/她可以考慮的。 – RAS

7

row_number有一個技巧,不涉及排序所有行。

試試這個:

SELECT columName 
FROM (SELECT ROW_NUMBER() OVER(ORDER BY (select NULL as noorder)) AS RowNum, * 
     FROM tableName 
    ) as alias 
WHERE RowNum BETWEEN 10 AND 20 

你不能在order by使用恆定。但是,您可以使用一個表達式來計算常量。 SQL Server能夠識別這一點,並正好返回遇到的行,正確列舉。

+0

我不確定這可以如何幫助。如果在沒有顯式排序的情況下應用ROW_NUMBER(),情況會不會是這樣:分頁將是無用的(以任意順序呈現)? –

+0

我發現使用這個構造,行號被分配爲行生成。或者,更具體地說,似乎沒有對錶格進行中間排序(至少在性能方面)。當使用'SELECT INTO'時,我通常使用它來爲行分配數字標識符。而且,行號是任意的,但是問題中的查詢沒有'order by'子句。 –

+0

但是,觀察<>保證。我確定演示文稿的順序很重要,但爲了簡潔起見,這些問題通常都會被排除在外,而不是因爲他們想要鼓勵可能提供任意結果的答案。 –

3

爲什麼你認爲SQL Server會評估整個內部查詢?假設你的排序列被索引,它只會讀取前20個值。如果你真的很緊張,你可以這樣做:

Select 
    Id 
From (
    Select Top 20 -- note top 20 
    Row_Number() Over(Order By Id) As RowNum, 
    Id 
    From 
    dbo.Test 
    Order By 
    Id 
) As alias 
Where 
    RowNum Between 10 And 20 
Order By 
    Id 

,但我敢肯定的查詢計劃是一樣的兩種方式。

(真的)按照Aaron的評論修正。

http://sqlfiddle.com/#!3/db162/6

+0

從技術上講,你需要一個ORDER BY。內部選擇不是*保證*以與ROW_NUMBER()應用的順序相同的順序返回行,即使這在多數情況下可能會出現。還要注意,當你瀏覽第二,第三,......第500頁時,內部查詢變得越來越昂貴。理想情況下,解決方案將提供線性性能。 –

+0

你需要像跳過列表那樣以無狀態的方式來做到這一點。我不認爲SQL Server有一個索引結構,它提供了不斷的性能來移動到索引中的第n個位置。如果底層集合不變,您可以做得更好,然後您可以預先計算頁面偏移量並將它們存儲在單獨的表中。感謝修復重新排序外部查詢。 – Laurence

+0

內部查詢實際上是需要訂單的外部查詢(外部用於演示目的,但內部需要確保正確的行選擇)。另外,我並沒有提出任何關於提供無狀態的東西......用戶期望在滾動時底層數據可以改變。但是,尋求第n頁*在SQL Server中可以是相對線性的,但是如果你這樣做的話,則不能通過SELECT TOP 10 FROM(SELECT TOP(page * pagesize)FROM big table)來實現。' –

0

還有一個選項

SELECT TOP(11) columName 
FROM dbo.tableName 
ORDER BY 
CASE WHEN ROW_NUMBER() OVER (ORDER BY someId) BETWEEN 10 AND 20 
    THEN ROW_NUMBER() OVER (ORDER BY someId) ELSE NULL END DESC 
0

您可以創建一個臨時表是有序的,你要喜歡的方式:

SELECT ROW_NUMBER()OVER(ORDER BY someId)AS ROWNUM ,* FROM tableName into ## tempTable ...

這樣你就可以得到有序的行列表秒。 ,並可以通過行號查詢後續時間,而不是多次執行內部查詢。