t-SQL查找每个组的前10个记录

时间:2013-04-30 15:17:09

标签: sql tsql subquery row-number

我想弄清楚如何为每组Trans.TranSID返回前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名。

2 个答案:

答案 0 :(得分: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以抓取任何每组记录数。

答案 1 :(得分: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