创建前十名但除了Top 9之外的所有内容

时间:2012-11-22 16:05:18

标签: tsql common-table-expression

我想要做的是拥有前10名,但是第10名被称为“其他”,其中所有内容的总和位于其中的前9位且总数为10。所以基本上它看起来像这样:

ReportingDate   FundCode    Currency            Duration Contribution   Percentage
31/10/2012      1111        Malaysian Ringgit   0.5                     14.6
31/10/2012      1111        Turkish Lira        0.3                     13.5
31/10/2012      1111        Russian Rouble      0.5                     11.9
31/10/2012      1111        Indunesian Rupiah   0.6                     11.7
31/10/2012      1111        Mexican Peso        0.6                     11.7
31/10/2012      1111        Polish Zloty        0.3                     10.2
31/10/2012      1111        Mexican Peso        0.4                     10.1
31/10/2012      1111        Polish Zloty        0.3                      9.9
31/10/2012      1111        South African Rand  0.2                      5.8
31/10/2012      1111        Brazilian Real      0.3                      2.0
31/10/2012      1111        Other               0.6                     -1.4
31/10/2012      1111        Total               4.6                    100.0

我的代码目前看起来像这样:

;;WITH CTE AS
(
SELECT 
    ReportingDate
,   PortfolioID
,   DV.dmv_nme AS Currency
,   RANK() OVER (PARTITION BY PortfolioID ORDER BY SUM(Percentage) DESC) AS [Rank]
,   ISNULL(CAST(SUM(DurationContribution)/100.0 AS DECIMAL(22,1)),0)    AS [Duration Contribution]
,   CAST(SUM(Percentage) AS DECIMAL(22,1))  AS [Weight]

FROM @Worktable as WT

INNER JOIN dw_domain_value AS DV
    ON DV.dmv_value = WT.Currency
    AND DV.data_cls_num = 2

GROUP BY    WT.ReportingDate
    ,   WT.PortfolioID
    ,   DV.dmv_nme
)

SELECT 
ReportingDate
, PortfolioID
, Currency
, [Rank]
, [Duration Contribution]
, [Weight]
FROM CTE
WHERE [Rank] <= 10
ORDER BY ReportingDate, PortfolioID, [Rank], [Weight] DESC

所以这给了我十大罚款。那么我怎么能得到它,以便最后的第10行是“其他”,所有内容都排在前9位,并且最后还包括总数?

2 个答案:

答案 0 :(得分:0)

这是一个解决方案。但您可以将其移入CTE以获得更好的性能。

;;WITH CTE AS
(
SELECT 
ReportingDate
,PortfolioID
,DV.dmv_nme AS Currency
,RANK() OVER (PARTITION BY PortfolioID ORDER BY SUM(Percentage) DESC) AS [Rank]
,ISNULL(CAST(SUM(DurationContribution)/100.0 AS DECIMAL(22,1)),0) AS [Duration Contribution]
,CAST(SUM(Percentage) AS DECIMAL(22,1))  AS [Weight]

FROM @Worktable as WT

INNER JOIN dw_domain_value AS DV
ON DV.dmv_value = WT.Currency
AND DV.data_cls_num = 2

GROUP BY    WT.ReportingDate
,   WT.PortfolioID
,   DV.dmv_nme
)    

SELECT 
ReportingDate
, PortfolioID
, CASE WHEN [Rank] <= 10 THEN Currency ELSE 'Total' END As Currency
, SUM([Duration Contribution]) As [Duration Contribution]
, SUM([Weight]) As [Weight]
FROM CTE
GROUP BY
ReportingDate
, PortfolioID
, CASE WHEN [Rank] <= 10 THEN Currency ELSE 'Total' END As Currency
WITH ROLLUP
ORDER BY ReportingDate, PortfolioID, [Rank], [Weight] DESC

答案 1 :(得分:0)

为此,我决定不能使用CTE,因此最终必须将这些逐段插入到临时表中,如下所示:

/* Include only top 9 */
INSERT INTO @FinalOutput
SELECT 
        ReportingDate
    ,   PortfolioID
    ,   PortfolioNme
    ,   Currency
    ,   [Rank]
    ,   DurationContribution
    ,   [Weight]
FROM @WorktableGrouped

WHERE [Rank] <= 9

ORDER BY ReportingDate, PortfolioID, [Rank], [Weight] DESC

/* Aggregate everything outside the top 9 into other */
INSERT INTO @FinalOutput
SELECT 
        ReportingDate
    ,   PortfolioID
    ,   PortfolioNme
    ,   'Other'         AS Currency
    ,   10              AS [Rank]
    ,   SUM(DurationContribution) AS DurationContribution
    ,   SUM([Weight])   AS [Weight]
FROM @WorktableGrouped

WHERE [Rank] > 9

GROUP BY ReportingDate, PortfolioID, PortfolioNme

ORDER BY ReportingDate, PortfolioID, [Rank], [Weight] DESC

SELECT * FROM @FinalOutput

/* Final Select with roll up for total per portfolio */
SELECT 
    ReportingDate
,   PortfolioID
,   PortfolioNme

,   CASE 
        WHEN GROUPING_ID(ReportingDate, PortfolioID, PortfolioNme, Currency, [Rank]) = 3 THEN 'Total'
        ELSE Currency
    END                                                         AS Currency

,   CASE 
        WHEN GROUPING_ID(ReportingDate, PortfolioID, PortfolioNme, Currency, [Rank]) = 3 THEN 11
        ELSE [Rank]
    END                                                         AS [Rank]

,   ISNULL(CAST(SUM(DurationContribution) AS DECIMAL(22,1)),0)  AS [Duration Contribution]  
,   CAST(SUM([Weight]) AS DECIMAL(22,1))                        AS [Weight]
--, GROUPING_ID(ReportingDate, PortfolioID, PortfolioNme, Currency, [Rank])

FROM @FinalOutput

GROUP BY ReportingDate
, PortfolioID
, PortfolioNme
, Currency
, [Rank] WITH ROLLUP

HAVING GROUPING_ID(ReportingDate, PortfolioID, PortfolioNme, Currency, [Rank]) IN (0,3)

ORDER BY ReportingDate, PortfolioID, [Rank]