【问题标题】:How to group data correctly如何正确分组数据
【发布时间】:2012-06-18 15:50:42
【问题描述】:

我的最终目标是拥有一个如下所示的表格:

Maturity Band     AAA     AA     A    A-    BBB+     BBB-    BB+    BB   Total
Less Than 1 yr    2.63%   5%                2%                           9.63%
1 to 5 yrs                       5%         5%                           10%
5 to 10 yrs       5.00%                              5%                  10%
10 to 20 yrs                          2%                                 2%
More than 20 yrs  10%                                         6%    1%   17%
Total             17.63%   5%    5%   2%    7%       5%       6%    1%   48.63%

我创建的程序 (@Worktable) 中的表如下所示:

PortfolioID    IssueName    SandPRating    SandPRatingSort    MaturityBand    MaturitySort
XXXXX          Bond1        AAA            1                  Less than 1 yr  1
XXXXX          Bond2        AAA            1                  Less than 1 yr  1
XXXXX          Bond3        AA-            7                  5 to 10 yrs     3
XXXXX          Bond4        BBB+           8                  1 to 5 yrs      2
etc.......

SandPRatingSort 以 1 为最高排序,成熟度排序也是如此。

我的问题是我正在努力在我的程序中将表格编码为上述格式(对不起,如果这看起来很容易,但我对此比较陌生)。我可以按 MaturityBand 对其进行分组,但我如何将其按正确的顺序排列,以及如何以评级作为标题来实现百分比?顺便说一下,百分比是具有评级的债券数量占投资组合持有的所有债券的百分比。

到目前为止我得到的最好的就是这个支点:

SELECT MaturityBand, [AAA],[AA+],[AA],[AA-],[A+],[A],[A-],[BBB+],[BBB],[BBB-],[BB+],[BB],[BB-],[B+],[B],[B-],[CCC+],[CCC],[CCC-],[CC],[C],[DDD],[DD],[D],[N.R.],[N.A.],[WR]
FROM
(
SELECT
MaturityBand
,SandPRating
FROM @Worktable
WHERE SandPRating IS NOT NULL
GROUP BY MaturityBand, SandPRating, MaturitySort, SandPSort
) AS source
PIVOT
(
COUNT(SandPRating)
FOR SandPRating IN ([AAA],[AA+],[AA],[AA-],[A+],[A],[A-],[BBB+],[BBB],[BBB-],[BB+],[BB],[BB-],[B+],[B],[B-],[CCC+],[CCC],[CCC-],[CC],[C],[DDD],[DD],[D],[N.R.],[N.A.],[WR])
) AS pvt

支点没有做我想做的事。我如何获得百分比?我怎样才能得到列和行的总计?此外,枢轴中的计数仅返回 1,我怎样才能得到它来汇总每列的评分数,而不必对工作表进行大量的返工?

如果有正确的方向或一些指导,我们将不胜感激。

谢谢

【问题讨论】:

  • “Total Total”值不应该是 100% 而不是 48.63%? (我只是想正确理解百分比值背后的逻辑。)
  • 是的,它应该总计 100%,只是快速尝试写出一些测试数据。
  • 应该按债券价值加权百分比,还是真的只是计算持股?
  • 只计算持有量,并显示占总持有量的百分比。

标签: tsql group-by pivot cube rollup


【解决方案1】:

通过一些试验和错误以及其他帖子的一些帮助,我设法回答了我自己的问题。 CTE 非常有用,我很高兴我有这样的经历能够了解它的来龙去脉。

;WITH CTE
AS
(
SELECT  PortfolioID
        , MaturityBand
        , SandPRating
        , MaturitySort
        , SUM((1/RecNo)*100) AS Pct

FROM    @Worktable AS A
--WHERE SandPRating IS NOT NULL
Group by MaturitySort, MaturityBand, SandPRating, PortfolioID

UNION All

SELECT   PortfolioID
        , MaturityBand
        , 'SandPRating_Total' AS SandPRating
        , MaturitySort
        , COUNT(*) * 100.0
        /
        (
            SELECT COUNT(*)
            FROM     @Worktable AS B
            WHERE B.PortfolioID = A.PortfolioID
        ) AS Total_Pct
FROM    @Worktable AS A
--WHERE SandPRating IS NOT NULL 
GROUP BY  MaturitySort, MaturityBand, PortfolioID
)
, CTE2
AS
(
SELECT  Grouping_ID(SandPRating, MaturityBand, MaturitySort) AS ID

     , CASE 
        WHEN Grouping_ID(SandPRating, MaturityBand, MaturitySort) = 3 THEN 'Total' 
        ELSE MaturityBand 
       END                                              AS MaturityBand

     , SandPRating

     , CASE 
        WHEN Grouping_ID(SandPRating, MaturityBand, MaturitySort) = 3 THEN 1000 
        ELSE MaturitySort 
       END                                              AS MaturitySort

     , SUM(Pct) AS PCT

FROM    CTE
GROUP BY ROLLUP (SandPRating
     , MaturityBand
     , MaturitySort)
)
--PIVOT
SELECT  MaturityBand, [AAA],[AA+],[AA],[AA-],[A+],[A],[A-]
    ,[BBB+],[BBB],[BBB-],[BB+],[BB],[BB-],[B+],[B],[B-]
    ,[CCC+],[CCC],[CCC-],[CC],[C],[DDD],[DD],[D],[N.R.]
    ,[N.A.],[WR],[Unass],[SandPRating_Total]     
FROM    (   SELECT SandPRating, MaturityBand, MaturitySort, PCT 
        FROM Cte2
        WHERE   ID = 0 or ID = 3
    ) AS x

PIVOT   (SUM(PCT)
        FOR SandPRating
        IN  ([AAA],[AA+],[AA],[AA-],[A+],[A],[A-]
            ,[BBB+],[BBB],[BBB-],[BB+],[BB],[BB-],[B+],[B],[B-]
            ,[CCC+],[CCC],[CCC-],[CC],[C],[DDD],[DD],[D],[N.R.]
            ,[N.A.],[WR],[Unass],[SandPRating_Total])
    ) myPiv
ORDER BY MaturitySort

【讨论】:

    【解决方案2】:

    以下获取所有总数并计算所有项目的百分比值:

    SELECT *
    FROM (
      SELECT
        MaturitySort = COALESCE(MaturitySort, 2147483647),
        MaturityBand = COALESCE(MaturityBand, 'Total'),
        SandPRating  = COALESCE(SandPRating , 'Total'),
        [Percent]    =
          COUNT(*) * 100.0 /
          SUM(CASE WHEN MaturityBand IS NOT NULL AND SandPRating IS NOT NULL THEN COUNT(*) END) OVER ()
      FROM WorkTable
      GROUP BY
      CUBE(
        (MaturityBand, MaturitySort),
        (SandPRating)
      )
    ) s
    PIVOT (
      MAX([Percent]) FOR SandPRating IN (
        [AAA],[AA+],[AA],[AA-],[A+],[A],[A-],
        [BBB+],[BBB],[BBB-],[BB+],[BB],[BB-],[B+],[B],[B-],
        [CCC+],[CCC],[CCC-],[CC],[C],[DDD],[DD],[D],[N.R.],
        [N.A.],[WR],[Unass],[Total]
      )
    ) p
    ORDER BY MaturitySort
    

    如您所见,百分比值的计算使用聚合窗口函数 (SUM())。如果没有CUBE() 分组,我们可以只做SUM(COUNT(*)) OVER ()。但是对于CUBE(),它将包含不应包含的值(汇总计数)。解决它们的一种方法是测试 SandPRatingMaturityBand 是否为 NULL,因为当行包含汇总计数时,NULL 会替换其中一列或两列。

    当然,这假设两列,尤其是MaturityBand,都不能保存实际的NULL。省略汇总的更正确方法可能是测试 GROUPING(<i>column</i>) 的结果:如果它为两列返回 0,则将 COUNT(*) 包括在总数中:

    …
    [Percent]    =
      COUNT(*) * 100.0 /
      SUM(CASE WHEN GROUPING(MaturityBand) = 0 AND GROUPING(SandPRating) = 0 THEN COUNT(*) END) OVER ()
    …
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-12
      • 1970-01-01
      • 2021-12-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      相关资源
      最近更新 更多