2010-05-17 173 views
2

我的SQL查詢給列:訂購一個SQL查詢結果

  • product_id(這是一個整數)
  • pnl(這就是浮存 - 可以是負的)

我獲得超過100行。

我想根據abs(pnl)過濾前40行。 但結果應該僅按pnl列排序,而不是按abs(pnl)排序。

我想爲MSSQL 2005

做到這一點是有辦法做到這一點?

回答

7

你不能在一個步驟/陳述中做到這一點。 TOP x選擇將始終基於ORDER BY訂購說明。您不能根據ABS(pnl)選擇TOP 40,並且同時按其他順序排列。

您需要做的是兩步處理 - 使用CTE(公用表表達式)或臨時表 - 首先選擇按ABS(pnl)排序的TOP 40行,然後按pnl對結果集進行排序。

喜歡的東西:

WITH Top40Rows AS 
(
    SELECT TOP 40 product_id, pnl 
    ORDER BY ABS(pnl) 
) 
SELECT product_id, pnl 
FROM Top40Rows 
ORDER BY pnl 
+1

+!:你是第一個。 – 2010-05-17 20:20:40

3

假設的product_id不表的主鍵,你可以做這樣的事情:

Select ... 
From Table 
    Join (
      Select TOP 40 TablePK 
      From Table 
      Order by Abs(pnl) Desc 
      ) As Z 
     On Table.TablePK = Z.TablePK 
Order By Table.pnl ASC  

由於OMG小馬,所提到的,你可以這樣做作爲單個派生表:

Select ... 
From (
     Select TOP 40 ..... 
     From Table 
     Order by Abs(pnl) Desc 
     ) As Z 
Order By Z.pnl ASC  

如果你想使用CTE,那麼我會用RO W_NUMBER功能:

With RankedItems As 
    (
    Select ... 
     , ROW_NUMBER() OVER (ORDER BY Abs(Table.pnl)) As ItemRank 
    From Table 
    ) 
Select 
From RankedItems 
Where ItemRank <= 40 
Order By pnl ASC 
+0

@OMG小馬 - 我可以使用交叉連接或存在語句來做到這一點,但我認爲內部連接更簡單。 – Thomas 2010-05-17 20:25:20

+0

@OMG小馬 - 我想我可以使整個TOP操作一個派生表,這將消除連接。 – Thomas 2010-05-17 20:26:13

+0

+1:對於更新,但ROW_NUMBER不是很好的選擇,因爲它會解析所有的表格內容。 – 2010-05-17 20:32:02

0

只是爲了保持完整性,這是一樣的@marc_s,但不使用CTE:

SELECT product_id, pnl FROM (
    SELECT TOP 40 product_id, pnl FROM tbl ORDER BY abs(pnl)) x 
ORDER BY pnl