SQL Server SQL中的线性插值

xggvc2p6  于 2022-11-28  发布在  其他
关注(0)|答案(1)|浏览(173)

我处理同一年的撞车事故和里程数,即表中的年份。每条记录都有撞车事故,但没有年里程数。对于某些客户,里程数的NULL可能位于时间段的开始或结束处。此外,几个年度里程记录也可能丢失。我不知道如何克服这一点。我试着用CASE语句来做,但是我不知道如何正确地编码。这个问题需要用SQL和SQL Server来解决。
这是输出的样子,我需要有每一个客户的每一年的里程数。我从专有数据库中提取的信息和记录本身应该是原封不动的。我只需要在查询中的代码,这将修改我的当前输出,以输出我每年的里程数。我感谢任何输入!
| 年份|客户|崩溃次数|年度_里程|
| - -|- -|- -|- -|
| 二〇 〇九年|一百二十三|五个|小行星3453453|
| 二〇一〇年|一百二十三|一个|空值|
| 二〇一一年|一百二十三|第0页|小行星54545|
| 二〇一二年|一百二十三|十四|小行星37645743|
| 二〇一三年|一百二十三|三个|六三四五三四五三|
| 二〇一四年|一百二十三|四个|空值|
| 二〇一五年|一百二十三|十五|小行星6346747|
| 二〇一六年|一百二十三|第0页|空值|
| 二〇一七年|一百二十三|2个|小行星534534|
| 二〇一八年|一百二十三|七个|空值|
| 二〇一九年|一百二十三|十一|空值|
| 小行星2020|一百二十三|十五|小行星565435|
| 小行星2021|一百二十三|十二|小行星474567546|
| 小行星2022|一百二十三|七个|空值|
预期结果
| 年份|客户|崩溃次数|年度_里程|
| - -|- -|- -|- -|
| 二〇 〇九年|一百二十三|五个|小行星3453453|
| 二〇一〇年|一百二十三|一个|175399(采用先前值)|
| 二〇一一年|一百二十三|第0页|小行星54545|
| 二〇一二年|一百二十三|十四|小行星37645743|
| 二〇一三年|一百二十三|三个|六三四五三四五三|
| 二〇一四年|一百二十三|四个|34900100(2个相邻值的平均值)|
| 二〇一五年|一百二十三|十五|小行星6346747|
| 二〇一六年|一百二十三|第0页|3440641(2个相邻值的平均值)|
| 二〇一七年|一百二十三|2个|小行星534534|
| 二〇一八年|一百二十三|七个|534534(采用先前值)|
| 二〇一九年|一百二十三|十一|549985(2个相邻值的平均值)|
| 小行星2020|一百二十三|十五|小行星565435|
| 小行星2021|一百二十三|十二|小行星474567546|
| 小行星2022|一百二十三|七个|474567546(采用先前值)|

SELECT Year, 
       Customer,
       Crashes,
       CASE
         WHEN Annual_Mlg IS NOT NULL THEN Annual_Mlg
         WHEN Annual_Mlg IS NULL THEN
           CASE
             WHEN PREV.Annual_Mlg IS NOT NULL
              AND NEXT.Annual_Mlg IS NOT NULL
               THEN ( PREV.Annual_Mlg + NEXT.Annual_Mlg ) / 2
             ELSE 0
           END
       END AS Annual_Mlg 
FROM #table

上面的代码不工作,但我只是需要开始以某种方式,我目前有什么。我知道我需要做什么,我只是不知道如何在SQL代码。

roejwanj

roejwanj1#

您对#table的使用说明您正在使用MS SQL Server(一个临时表,可能在存储过程中)。
您需要:

  • 选择#table中的所有行
  • 与上一年的匹配行(如果有)连接,以及
  • 与下一年的匹配行(如果有)连接

这就很简单了。假设#table上的主键由yearcustomer列组成,应该可以执行如下操作:

select t.year     ,
       t.customer ,
       t.crashes  ,
       annual_milage = coalesce(
         t.annual_milage ,
         ( coalesce( p.annual_mileage, 0 ) +
           coalesce( n.annual_mileage, 0 )
         ) / 2
       )
from      #table t                            -- take all the rows
left join #table p on p.year     = t.year - 1 -- with the matching row for
                  and p.customer = t.customer --   the previous year (if any)
left join #table n on n.year     = t.year + 1 -- and the matching row for
                  and n.customer = t.customer --   the next year (if any)

备注:

  • 如果上一年或下一年不存在,您可以选择默认值(零?任意值?)
  • 上一年/下一年是否保证为当前年度+/- 1?

如果没有,您可能必须使用 * 派生表 * 作为上一年/下一年数据的源,选择最近的上一年/下一年(这类事情会使查询非常复杂)。

已编辑备注:

如果每个客户的年份都不连续,因此给定客户的“上一年”和“下一年”不一定是当前年份+/- 1,那么类似这样的方法可能是查找上一年/下一年的最直接方法。
我们在from子句中使用 derived table,并使用 ranking functionrow_number()函数为每个客户分配一个序号来代替year。

select row_nbr = row_number() over (
                   partition by x.customer
                   order by     x.year
                 ) ,
       x.*
from #table x

将产生以下结果:
| 行号|顾客|年份|一个人。|
| - -|- -|- -|- -|
| 一个|一百二十三|小行星9067|一个人。|
| 2个|一百二十三|小行星9067|一个人。|
| 三个|一百二十三|一九九五年|一个人。|
| 四个|一百二十三|小行星2020|一个人。|
| 一个|四百五十六|二OO一年|一个人。|
| 2个|四百五十六|二〇 〇五年|一个人。|
| 三个|四百五十六|小行星2020|一个人。|
这让我们想到了

select year           = t.year     ,
       customer       = t.customer ,
       crashes        = t.crashes  ,
       annual_mileage = coalesce(
                          t.mileage,
                          coalesce(
                            t.annual_mileage,
                            (
                              coalesce(p.annual_mileage,0) +
                              coalesce(n.annual_mileage,0)
                            ) / 2
                          ),
                        )
from (
       select row_nbr = row_number() over (
                          partition by x.customer
                          order by     x.year
                        ) ,
              x.*
       from #table x
     ) t
left join #table p on p.customer = t.customer and p.row_nbr = t.row_nbr-1
left join #table n on n.customer = t.customer and n.row_nbr = t.row_nbr+1

相关问题