-1

目前我有一个要求,需要一个看起来像这样的表格:

Instrument  Long  Short  2013  2014  2015  2016  2017  2018  2019   2020  2021  2022 ....    
Fixed       41    41     35    35    35    35    35    35    35     53    25    25
Index       16    16     22    22    22    32    12    12    12     12    12    12
Credits     29    29     41    16    16    16    16    16    16     16    16    16
Short term  12    12     5     5     5     5     5     5     5      5     5     17

我的工作台如下所示:

Instrument  Long  Short  Annual Coupon  Maturity Date  Instrument ID
Fixed       10    10     10             01/01/2025     1   
Index       5     5      10             10/05/2016     2
Credits     15    15     16             25/06/2020     3
Short term  12    12     5              31/10/2022     4
Fixed       13    13     15             31/03/2030     5
Fixed       18    18     10             31/01/2019     6
Credits     14    14     11             31/12/2013     7
Index       11    11     12             31/10/2040     8
..... etc

所以基本上,枢轴中的多头和空头应该是每个不同工具 ID 的总和。然后对于每一年,我需要将每张年票的总和计算到到期日,在该年,多头和票面利率相加。

我的想法是,我必须创建一个 while 循环,该循环将在一个表中填充每个工具每年的记录,直到到期日,这样我就可以使用 sql pivot 以某种方式进行旋转。这看起来可行吗?关于这样做的最佳方式的任何其他想法,特别是我可能需要关于 while 循环的帮助?

4

1 回答 1

0

以下解决方案使用数字表展开表中的范围,对展开集中的某些数据列执行一些特殊处理,最后对结果进行透视:

WITH unfolded AS (
  SELECT
    t.Instrument,
    Long      = SUM(z.Long ) OVER (PARTITION BY Instrument),
    Short     = SUM(z.Short) OVER (PARTITION BY Instrument),
    Year      = y.Number,
    YearValue = t.AnnualCoupon + z.Long + z.Short
  FROM YourTable t
  CROSS APPLY (SELECT YEAR(t.MaturityDate)) x (Year)
  INNER JOIN numbers y ON y.Number BETWEEN YEAR(GETDATE()) AND x.Year
  CROSS APPLY (
    SELECT
      Long  = CASE y.Number WHEN x.Year THEN t.Long  ELSE 0 END,
      Short = CASE y.Number WHEN x.Year THEN t.Short ELSE 0 END
  ) z (Long, Short)
),
pivoted AS (
  SELECT *
  FROM unfolded
  PIVOT (
    SUM(YearValue) FOR Year IN ([2013], [2014], [2015], [2016], [2017], [2018], [2019], [2020],
                [2021], [2022], [2023], [2024], [2025], [2026], [2027], [2028], [2029], [2030],
                [2031], [2032], [2033], [2034], [2035], [2036], [2037], [2038], [2039], [2040])
  ) p
)
SELECT *
FROM pivoted
;

它返回静态范围年份的结果。要将其用于动态计算的年份范围,您首先需要将年份列表准备为 CSV 字符串,如下所示:

SET @columnlist = STUFF(
  (
    SELECT  ', [' + CAST(Number) + ']'
    FROM numbers
    WHERE Number BETWEEN YEAR(GETDATE())
                     AND (SELECT YEAR(MAX(MaturityDate)) FROM YourTable)
    ORDER BY Number
  FOR XML PATH ('')
  ),
  1, 2, ''
);

然后将其放入查询的动态 SQL 版本中:

SET @sql = N'
WITH unfolded AS (
...
  PIVOT (
    SUM(YearValue) FOR Year IN (' + @columnlist + ')
  ) p
)
SELECT *
FROM pivoted;
';

并执行结果:

EXECUTE(@sql);

您可以在 SQL Fiddle尝试此解决方案。

于 2013-07-24T18:53:22.720 回答