1

我正在为一些管理信息的报告构建前 10 名,该报告以以下脚本结尾:

IF @ReportType = 'SectorEQ'

BEGIN
/* Final Select with roll up for total per portfolio */
    SELECT 
            CONVERT(VARCHAR, ReportingDate, 103)    AS ReportingDate
        ,   PortfolioID                             AS FundCode
        ,   PortfolioNme                            AS FundName

        ,   CASE 
                WHEN GROUPING_ID(ReportingDate, PortfolioID, PortfolioNme, Sector, [Rank], [Weight]) = 7 THEN 'Total'
                ELSE Sector
                END                                 AS Sector

        ,   CASE 
                WHEN GROUPING_ID(ReportingDate, PortfolioID, PortfolioNme, Sector, [Rank], [Weight]) = 7 THEN 102
                ELSE [Rank]
            END                                     AS [Rank]

        ,   CAST(SUM([Weight]) AS DECIMAL(22,1))    AS Percentage

    FROM @FinalOutputEQ_CS

    GROUP BY    ReportingDate
            ,   PortfolioID
            ,   PortfolioNme
            ,   Sector
            ,   [Rank]
            ,   [Weight] WITH ROLLUP

    HAVING GROUPING_ID(ReportingDate, PortfolioID, PortfolioNme, Sector, [Rank], [Weight]) IN (1,7)

    ORDER BY    ReportingDate
            ,   PortfolioID
            ,   [Rank]

如您所见,百分比四舍五入到小数点后 1 位,这可能会导致舍入问题,因为到小数点后 1 位的百分比之和可能小于或大于 100,即 100.1 或 99.9。我需要做的是确保四舍五入到小数点后 1 位的百分比都等于 100.0。

我想做的是检查四舍五入百分比的总和是否等于 100.0,如果不是,则取前 1 名并减去其百分比的差值。

我对如何做到这一点有一些想法,但我想知道在不减慢进程的情况下确保快速有效地运行的最佳方法是什么?

编辑:示例表

ReportingDate   FundCode    FundName    Sector                   Rank   Percentage
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Consumer Discretionary      1   16.1
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Health Care                 2   13.8
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Information Technology      3   11.8
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Telecommunication Services  4   10.3
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Consumer Staples            5   10.1
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Industrials                 6   8.7
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Financials                  7   6.8
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Materials                   8   6.5
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Energy                      9   5.2
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Utilities                   10  0.7
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Cash and Bonds              101 10.1
28/02/2013  XXXXXXXX    XXXXXXXXXXXXXXX Total                       102 100.1
4

2 回答 2

0

只是没有十进制类型可以排到第十位吗?

例如:

declare @decimal decimal (16,4) = 123456.7890;    ;

select cast(@decimal as decimal(16,0))

代替

select cast(@decimal as decimal(16,1))

另外,为什么你的值会变成 22 个值?(十进制类型中的第一个位置)如果您担心 proc 的效率,那么需要存储大量数据。我通常对第一个数字很吝啬,很少超过 16,除非有非常大的数据返回。

编辑舍入第十位:

declare @decimal decimal (16,1) = 123456.5;   -- you can change this as needed to see how it will change

-- if you want to do rounding then you need to determine if the tenth position is above or greater than five
-- you could do this in a function if you want.  You need to determine a return of 1 or 0 based on rounding
declare @logic int = case when right(@decimal,1) >= 5 then 1 else 0 end

-- find the integer value WITHOUT the decimal places and then add the logic variable
select left(@decimal, len(@decimal) - 2) + @logic as Rounded
于 2013-03-08T17:50:40.747 回答
0

我可以为此解决的唯一解决方案是创建下面的脚本,该脚本基本上总结了细节以给出总数。然后在我的 CTE 之后,我从前 1 名和总数中减去了这个:

IF @ReportType = 'SectorEQ'

BEGIN
    INSERT INTO @RoundingDifference
        SELECT
                PortfolioID
            ,   CAST(SUM([Weight])-100 AS DECIMAL(22,1)) AS [Weight]

        FROM @FinalOutputEQ_CS

        WHERE Sector <> 'Total'

        GROUP BY        
                ReportingDate
            ,   PortfolioID
            ,   PortfolioNme

END

IF @ReportType = 'SectorEQ'

BEGIN
;;WITH CTE AS
    (
/* Final Select with roll up for total per portfolio */
    SELECT 
            CONVERT(VARCHAR, ReportingDate, 103)    AS ReportingDate
        ,   PortfolioID                             AS FundCode
        ,   PortfolioNme                            AS FundName

        ,   CASE 
                WHEN GROUPING_ID(ReportingDate, PortfolioID, PortfolioNme, Sector, [Rank], [Weight]) = 7 THEN 'Total'
                ELSE Sector
                END                                 AS Sector

        ,   CASE 
                WHEN GROUPING_ID(ReportingDate, PortfolioID, PortfolioNme, Sector, [Rank], [Weight]) = 7 THEN 102
                ELSE [Rank]
            END                                     AS [Rank]

        ,   CAST(SUM([Weight]) AS DECIMAL(22,1))    AS Percentage

    FROM @FinalOutputEQ_CS

    GROUP BY    ReportingDate
            ,   PortfolioID
            ,   PortfolioNme
            ,   Sector
            ,   [Rank]
            ,   [Weight] WITH ROLLUP

    HAVING GROUPING_ID(ReportingDate, PortfolioID, PortfolioNme, Sector, [Rank], [Weight]) IN (1,7)
    )
    SELECT 
        ReportingDate
    ,   FundCode
    ,   FundName
    ,   Sector
    ,   [Rank]

    ,   CASE 
            WHEN [Rank]IN (1,102) THEN Percentage - RD.[Weight]
            ELSE Percentage
        END     AS Percentage

    FROM CTE AS CTE

        INNER JOIN @RoundingDifference AS RD
        ON RD.PortfolioID = CTE.FundCode

    ORDER BY    ReportingDate
            ,   FundCode
            ,   [Rank]

END
于 2013-03-15T11:29:39.873 回答