SQL Server View : how to add missing rows using interpolation

标签 sql sql-server sql-view linear-interpolation

遇到问题。

我定义了一个表来保存每日国库的值(value) yield curve .

这是一个非常简单的表,用于值的历史查找。

年份 4 的表中存在明显的一些空白, 6 , 8 , 9 , 11-1921-29 .

计算年份 4 的公式非常简单。它是 0.5*Year3Value + 0.5*Year5Value .

问题是我怎么写VIEW那可以归还逝去的岁月?

我可能可以在存储过程中完成它,但最终结果需要是一个 View 。

最佳答案

假设 Tom H. 认为您真正想要的是线性插值,并且不仅缺少年份,还缺少月份,您需要将每个计算基于 MONTH,而不是 YEAR。

对于下面的代码,我假设您有 2 个表(其中一个可以作为 View 的一部分计算):

  • 产量:包含真实数据和以月数而不是名称存储的 PeriodM。如果您将 PeriodName 存储在那里,您只需要加入表:
  • 周期(可以在如图所示的 View 中计算):存储周期名称和它代表的月数

  • 以下代码必须有效(您只需要基于它创建一个 View ):
    WITH "Period" (PeriodM, PeriodName) AS (
        -- // I would store it as another table basically, but having it as part of the view would do
                    SELECT  01, '1 mo'
        UNION ALL   SELECT  02, '2 mo' -- // data not stored
        UNION ALL   SELECT  03, '3 mo'
        UNION ALL   SELECT  06, '6 mo'
        UNION ALL   SELECT  12, '1 yr'
        UNION ALL   SELECT  24, '2 yr'
        UNION ALL   SELECT  36, '3 yr'
        UNION ALL   SELECT  48, '4 yr' -- // data not stored
        UNION ALL   SELECT  60, '5 yr'
        UNION ALL   SELECT  72, '6 yr' -- // data not stored
        UNION ALL   SELECT  84, '7 yr'
        UNION ALL   SELECT  96, '8 yr' -- // data not stored
        UNION ALL   SELECT 108, '9 yr' -- // data not stored
        UNION ALL   SELECT 120, '10 yr'
        -- ... // add more
        UNION ALL   SELECT 240, '20 yr'
        -- ... // add more
        UNION ALL   SELECT 360, '30 yr'
    )
    , "Yield" (ID, PeriodM, Date, Value) AS (
        -- // ** This is the TABLE your data is stored in **
        -- // 
        -- // value of ID column is not important, but it must be unique (you may have your PK)
        -- // ... it is used for a Tie-Breaker type of JOIN in the view
        -- //
        -- // This is just a test data:
                    SELECT 101, 01 /* '1 mo'*/, '2009-05-01', 0.06
        UNION ALL   SELECT 102, 03 /* '3 mo'*/, '2009-05-01', 0.16
        UNION ALL   SELECT 103, 06 /* '6 mo'*/, '2009-05-01', 0.31
        UNION ALL   SELECT 104, 12 /* '1 yr'*/, '2009-05-01', 0.49
        UNION ALL   SELECT 105, 24 /* '2 yr'*/, '2009-05-01', 0.92
        UNION ALL   SELECT 346, 36 /* '3 yr'*/, '2009-05-01', 1.39
        UNION ALL   SELECT 237, 60 /* '5 yr'*/, '2009-05-01', 2.03
        UNION ALL   SELECT 238, 84 /* '7 yr'*/, '2009-05-01', 2.72
        UNION ALL   SELECT 239,120 /*'10 yr'*/, '2009-05-01', 3.21
        UNION ALL   SELECT 240,240 /*'20 yr'*/, '2009-05-01', 4.14
        UNION ALL   SELECT 250,360 /*'30 yr'*/, '2009-05-01', 4.09
    )
    , "ReportingDate" ("Date") AS (
        -- // this should be a part of the view (or a separate table)
        SELECT DISTINCT Date FROM "Yield"
    )
    
    -- // This is the Final VIEW that you want given the data structure as above
    SELECT      d.Date, p.PeriodName, --//p.PeriodM,
                CAST(
                    COALESCE(y_curr.Value,
                        (   (p.PeriodM - y_prev.PeriodM) * y_prev.Value
                        +   (y_next.PeriodM - p.PeriodM) * y_next.Value
                        ) / (y_next.PeriodM - y_prev.PeriodM)
                    ) AS DECIMAL(9,4) -- // TODO: cast to your type if not FLOAT
                )  AS Value
    FROM        "Period" p
    CROSS JOIN  "ReportingDate" d
    LEFT JOIN   "Yield" y_curr
            ON  y_curr.Date = d.Date
            AND y_curr.PeriodM = p.PeriodM
    LEFT JOIN   "Yield" y_prev
            ON  y_prev.ID = (SELECT TOP 1 y.ID FROM Yield y WHERE y.Date = d.Date AND y.PeriodM <= p.PeriodM ORDER BY y.PeriodM DESC)
    LEFT JOIN   "Yield" y_next
            ON  y_next.ID = (SELECT TOP 1 y.ID FROM Yield y WHERE y.Date = d.Date AND y.PeriodM >= p.PeriodM ORDER BY y.PeriodM ASC)
    
    --//WHERE       d.Date = '2009-05-01'
    

    关于SQL Server View : how to add missing rows using interpolation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/920776/

    相关文章:

    mysql - 如何只用一条sql语句创建一个view来达到这个目的呢?

    java - JDBC 连接字符串与 selectMethod=cursor 断开连接

    sql - 表列之间的一对多关系。分组和查找组合

    mysql - Rails 3.1 - Heroku 上 mySQL 和 PostgreSQL 之间巨大的查询时间差异

    sql - Delphi:如何将表结构转化为对象

    sql-server - 通过预过滤结果加速 SQL View

    mysql - 在 MySQL 中用连接替换子查询

    c# - 如何强制 SqlCommand 不将参数编码为 un​​icode/nvarchar?

    SQL - 对 3.77 亿个表的性能低下的 SELECT 查询

    mysql - 从 View 中选择聚合/计算列