如何使用递归 CTE 为数据集添加分辨率

How to use recursive CTE to add resolution to a data set

我正在尝试创建一个递归 CTE 语句,在数据点之间添加空白行,稍后将用于插值。我是 SQL 的初学者,这是我第一次使用 CTE,并且在找到正确的方法时遇到了一些困难。

经过一些研究,我尝试对下面提供的代码进行一些不同的细微改动,但还没有掌握足够好的理解来查看我的问题。下面的代码应该通过每 4 小时从样本数据集中进行一次观察来模拟稀疏采样,第二部分应该每 0.1 小时添加具有相应 x 值的行,稍后将用从三次样条派生的插值填充。

--样本数据

create table #temperatures (hour integer, temperature double precision);
insert into #temperatures (hour, temperature) values
(0,18.5),
(1,16.9),
(2,15.3),
(3,14.1),
(4,13.8),
(5,14.7),
(6,14.7),
(7,13.5),
(8,12.2),
(9,11.4),
(10,10.9),
(11,10.5),
(12,12.3),
(13,16.4),
(14,22.3),
(15,27.2),
(16,31.1),
(17,34),
(18,35.6),
(19,33.1),
(20,25.1),
(21,21.3),
(22,22.3),
(23,20.3),
(24,18.4),
(25,16.8),
(26,15.6),
(27,15.4),
(28,14.7),
(29,14.1),
(30,14.2),
(31,14),
(32,13.9),
(33,13.9),
(34,13.6),
(35,13.1),
(36,15),
(37,18.2),
(38,21.8),
(39,24.1),
(40,25.7),
(41,29.9),
(42,28.9),
(43,31.7),
(44,29.4),
(45,30.7),
(46,29.9),
(47,27);

--1

WITH xy (x,y)
AS 
    (
  SELECT  TOP 12
    CAST(hour AS double precision) AS x
    ,temperature AS y 
    FROM #temperatures 
    WHERE cast(hour as integer) % 4 = 0
   )

Select x,y
INTO #xy
FROM xy

Select [x] As [x_input]
INTO #x_series
FROM #xy

--2

    with recursive
  , x_series(input_x) as (
    select
      min(x)
    from
      #xy
    union all
    select
      input_x + 0.1
    from
      x_series
    where
      input_x + 0.1 < (select max(x) from x)
  )
  , x_coordinate as (
  select
    input_x
    , max(x) over(order by input_x) as previous_x
  from
    x_series
  left join
    #xy on abs(x_series.input_x - xy.x) < 0.001
  )

第一个 CTE 按预期工作并生成 12 个列表(两天内每 4 小时一个样本),但第二个 CTE 产生语法错误。预期的输出类似于

(4,13.8), (4.1,null/0), (4.2,null/0),....., (8,12.2)

使用你在--1中产生的temp table #xy,下面会给你一个x系列:

;with x_series(input_x)
as
(
    select min(x) AS input_x
    from #xy
    union all
    select input_x + 0.1
    from x_series
    where input_x + 0.1 < (select max(x) from #xy)
)
SELECT * FROM x_series;

我认为您在这里不需要递归 CTE。我认为这样的解决方案将是更好的方法。相应修改。

DECLARE @max_value FLOAT = 
    (SELECT MAX(hour) FROM  #temperatures) * 10

INSERT INTO #temperatures (hour, temperature)
SELECT X.N / 10, NULL
FROM (
    select CAST(ROW_NUMBER() over(order by t1.number) AS FLOAT) AS N
    from   master..spt_values t1 
           cross join master..spt_values t2
) X
WHERE X.N <= @max_value
    AND X.N NOT IN (SELECT hour FROM #temperatures)

我认为你不需要递归。

这个怎么样:

SQL DEMO

SELECT DISTINCT n = number *1.0 /10 , #xy.x, #xy.y
FROM master..[spt_values] step
LEFT JOIN #xy
  ON step.number*1.0 /10  = #xy.x
WHERE number BETWEEN 40 AND 480

This 480 is based on the two days you mention.

输出

你甚至不需要时间 table

SELECT DISTINCT n = number *1.0 /10 , #temperatures.temperature
FROM master..[spt_values] step
LEFT JOIN #temperatures
  ON step.number *1.0 / 10  = #temperatures.hour
 AND  #temperatures.hour % 4 = 0
WHERE number BETWEEN 40 AND 480;