2013-04-30 83 views
7

我想弄清楚如何爲Trans.TranSID的每個組返回前10條記錄。t-SQL查找每個組的前10條記錄

SELECT a.ABID, a.ABName, t.TranSID, SUM(IIF(TranTypeID = 'CO', td.Qty * CAST(td.Price AS money) * - 1, 
         td.Qty * CAST(td.Price AS money))) AS TotalSales 
FROM   Trans t INNER JOIN 
         TransDetail td ON t.TranID = td.TranID INNER JOIN 
         ABook a ON t.TranABID = a.ABID 
WHERE  (t.TranDate BETWEEN CONVERT(DATETIME, '2012-01-01 00:00:00', 102) AND CONVERT(DATETIME, '2013-01-01 00:00:00', 102)) AND 
      t.TranTypeID in ('SO','CA','CO') AND (t.TranStatus <> 'V') 
GROUP BY a.ABID, a.ABName, t.TranSID 
HAVING (NOT (a.ABName LIKE '%cash%')) 
ORDER BY t.TranSID, TotalSales Desc 

我可以在select語句中添加「TOP 10」,但是不管組別如何,我都可以獲得前10名。有25組Trans.TranSID,我試圖讓每組只有前10名。

+0

包括一個基本的表結構和預期的輸出將幫助你得到答案。 – jTC 2013-04-30 15:40:17

+0

基本上有一個客戶賬戶表(Abook)和交易(Trans)以及交易詳情(TransDetail)表。非常簡單的結構。只需要爲每個客戶總結銷售額,然後將TranSID(這是交易發生的地點)的前10名結果分組。 – 2013-04-30 15:42:56

回答

10

我認爲你正在尋找ROW_NUMBER()PARTITION BY

SELECT * 
FROM (
    SELECT 
     ROW_NUMBER() OVER(PARTITION BY t.TranSID ORDER BY t.TranSID, SUM(IIF(TranTypeID = 'CO', td.Qty * CAST(td.Price AS money) * - 1, td.Qty * CAST(td.Price AS money))) DESC) as RowNum,    
     a.ABID, 
     a.ABName, 
     t.TranSID, 
     SUM(IIF(TranTypeID = 'CO', td.Qty * CAST(td.Price AS money) * - 1, td.Qty * CAST(td.Price AS money))) AS TotalSales 
    FROM Trans t 
     INNER JOIN TransDetail td 
      ON t.TranID = td.TranID 
     INNER JOIN ABook a 
      ON t.TranABID = a.ABID 
    WHERE (t.TranDate BETWEEN CONVERT(DATETIME, '2012-01-01 00:00:00', 102) AND CONVERT(DATETIME, '2013-01-01 00:00:00', 102)) 
     AND t.TranTypeID in ('SO','CA','CO') 
     AND (t.TranStatus <> 'V') 
    GROUP BY a.ABID, a.ABName, t.TranSID 
    HAVING (NOT (a.ABName LIKE '%cash%')) 
) a 
WHERE a.RowNum <=10 

這將行號分配給該組的每個記錄(由PARTITION定義的列,從1去到n。從那裏開始,你可以運行一個SELECT來抓取任意數量的記錄。

+0

運行該代碼時出現以下錯誤消息。消息1033,級別15,狀態1,行20 除非還指定了TOP,OFFSET或FOR XML,否則ORDER BY子句在視圖,內聯函數,派生表,子查詢和公用表表達式中無效。 – 2013-04-30 16:06:01

+0

@GaryGerson,我已經更新了我的腳本。嘗試刪除子查詢 – valverij 2013-04-30 16:09:32

+0

底部的'ORDER BY'是的。我實際上是在同一時間完成的。 – 2013-04-30 16:14:43

1

我不是特別熟悉t-sql,很遺憾我沒有訪問t-sql數據庫來測試這完成了你的目標

這就是說,我認爲這是你可以使用子查詢和ROW_NUMBER函數完成它的一種方法。

SELECT 
    * 
FROM (
    SELECT 
     a.ABID 
     , a.ABName 
     , t.TranSID 
     , SUM(IFF(TranTypeID = 'CO' 
      , td.Qty * CAST(td.Price AS MONEY) * -1 
      , td.Qty * CAST(td.Price AS MONEY))) AS TotalSales 
     , ROW_NUMBER() 
      OVER(PARTITION BY t.TranSID 
       ORDER BY SUM(IFF(TranTypeID = 'CO' 
        , td.Qty * CAST(td.Price AS MONEY) * -1 
        , td.Qty * CAST(td.Price AS MONEY))) DESC) AS row 
    FROM 
     Trans t 
     INNER JOIN TransDetail td 
     ON t.TranID = td.TranID 

     INNER JOIN ABook a 
     ON t.TranABID = a.ABID 

    WHERE 
     (t.TranDate BETWEEN CONVERT(DATETIME, '2012-01-01 00:00:00', 102) AND CONVERT(DATETIME, '2013-01-01 00:00:00', 102)) 
     AND t.TranTypeID in ('SO','CA','CO') 
     AND (t.TranStatus <> 'V') 

    GROUP BY 
     a.ABID 
     , a.ABName 
     , t.TranSID 

    HAVING 
     (NOT (a.ABName LIKE '%cash%')) 
) q 

WHERE 
    q.row <= 10 
+0

與上面相同,當我運行此操作時,出現以下錯誤消息。消息1033,級別15,狀態1,行20 除非還指定了TOP,OFFSET或FOR XML,否則ORDER BY子句在視圖,內聯函數,派生表,子查詢和公用表表達式中無效。 – 2013-04-30 16:06:28

+1

我相信你的第一個版本的問題是ROW_NUMBER()字段在sum函數中有「AS TotalSales」。你現在在那裏工作。 – 2013-04-30 16:16:45