SQL - 从每个类别的前20%中获取值的总和

时间:2014-03-04 23:29:32

标签: sql sql-server sql-server-2008 tsql

这个很棘手。

财务表的SecurityID,FundID和Value已按FundID分组,并在每个FundID中排名/排序

它可能看起来像这样(想象数百或记录):

+------+------------+--------+-------+
| Rank | SecurityID | FundID | Value |
+------+------------+--------+-------+
| 1    | 23         | A      | 5     |
| 2    | 43         | A      | 4     |
| 3    | 44         | A      | 3     |
| 1    | 72         | B      | 8     |
| 2    | 75         | B      | 7     |
| 3    | 76         | B      | 2     |
| 1    | 83         | C      | 5     |
+------+------------+--------+-------+

目标是获得每种基金类型中前20%的证券。然后从该20%得到值的总和。例如,如果基金类型A中有10个证券,那么我想总结前2个记录中的值。答案是9.

SQL可能如下所示:

SELECT SUM(Value) as TopTwenty, FundID
                        FROM @FinanceTable    
                        WHERE Rank <= ((SELECT  COUNT(*)
                                                FROM @FinanceTable WHERE FundID = 1) * .20)

                        GROUP BY FundID  

上述查询适用于FundID = 1.但是,我不想指定“Where FundID = 1”。相反,我希望它为所有FundID运行此查询。这是我难倒的部分。我想我可以用光标做到这一点。但有没有办法在没有光标的情况下这样做?

谢谢!

2 个答案:

答案 0 :(得分:2)

您可以使用窗口函数count(*)来获取每个基金的总行数。然后使用where子句进行过滤:

select FundID, sum(value)
from (select ft.*, count(*) over (partition by FundId) as cnt
      from @FinanceTable ft
     ) ft
where rank <= 0.2*cnt
group by FundId;

答案 1 :(得分:1)

;with FundCounts As
(
    Select FundID, Count(*) * 0.2 As TopTwentyCount
    From Finance
    Group By FundID
)
select F.FundID, Sum(Value) as TopTwentyValueSum
from Finance F
inner join FundCounts FC on F.FundID = FC.FundID
where F.[Rank] <= FC.TopTwentyCount 
group by F.FundID