从表中选择缺少的行

时间:2011-03-30 20:30:41

标签: sql math interpolation

temperature  decrease_capacity
----------    ----------------
125           5
150           10
175           15

...等 如果我想为温度= 166选择decrease_capacity,我将如何获得。

3 个答案:

答案 0 :(得分:0)

线性插值的数学运算是:

c1 + (t - t1) / (t2 - t1) * (c2 - c1)

t  = input tempurate
t1 = nearest lower temperature
t2 = nearest upper temperature
c1 = capacity belonging to t1
c2 = capacity belonging to t2

这是一些用来做数学运算的SQL:

declare @YourTable table (temperature int, decrease_capacity int)
insert @YourTable values (125, 5), (150, 10), (175, 15)

declare @temp int
set @temp = 166

select  case 
        when below.temperature is null then above.decrease_capacity
        when above.temperature is null then below.decrease_capacity
        else below.decrease_capacity + 1.0 *
             (@temp - below.temperature) / 
             (above.temperature - below.temperature) *
             (above.decrease_capacity - below.decrease_capacity)
        end
from    (
        select  min(temperature) as mintemp
        from    @YourTable 
        where   temperature >= @temp
        ) abovetemp
left join
        @YourTable above
on      above.temperature = abovetemp.mintemp
cross join
        (
        select  max(temperature) as maxtemp
        from    @YourTable 
        where   temperature < @temp
        ) belowtemp
left join
        @YourTable below
on      below.temperature = belowtemp.maxtemp

Example on odata.

答案 1 :(得分:0)

如果线性插值是期望的结果,那么以下极其丑陋,愚蠢且可能很慢的查询可能会产生该结果。我将字段名称缩短为tdc。我说“可能”,因为此查询存在巨大警告如上所述,它假设reduce_capacity值总是随着温度的升高而增加(我不知道这是否真实)。 select max(dc) from test where t <= 166是基于该假设的一部分。这也假设字段是浮点值(否则它将按写入方式进行整数数学运算)。

哦......并且警告#3。如果指定的温度低于或高于表中的所有温度值,这也会失败。

select (select max(dc) from test where t <= 166) + 
       (166 - (select max(t) from test where t <= 166)) * 
       ((select min(dc) from test where t >= 166) - 
        (select max(dc) from test where t <= 166)) / 
       ((select min(t) from test where t >= 166) - 
        (select max(t) from test where t <= 166))

将它实现为存储过程可能更有意义,只需执行单独的SELECT语句并从中计算线性插值结果。这将更容易阅读,几乎肯定更有效。

答案 2 :(得分:0)

您尚未说明RDBMS。这使用特定于SQL Server的TOP(可以替换为row_numberlimit取决于flavor)和SQL Server特定变量以便于测试。

如果没有2个数据点,我选择返回NULL

DECLARE @SearchTemp FLOAT = 166;

WITH T(temperature, decrease_capacity) AS
(
SELECT 125.0,5.0 UNION ALL
SELECT 150.0,10 UNION ALL
SELECT 175.0,15 
), T2 AS
(
SELECT TOP 1 'L' as bound, temperature, decrease_capacity
FROM T 
WHERE temperature <= @SearchTemp
ORDER BY temperature DESC
UNION ALL
SELECT TOP 1 'U' as bound,  temperature, decrease_capacity
FROM T 
WHERE temperature >= @SearchTemp
ORDER BY temperature 
)
SELECT CASE
         WHEN COUNT(*) = 2 THEN CASE
                                  WHEN COUNT(DISTINCT temperature) = 1 THEN MAX(decrease_capacity)
                                  ELSE ((@SearchTemp-MAX(CASE WHEN bound = 'L' THEN temperature END) )/(MAX(CASE WHEN bound = 'U' THEN temperature END) -MAX(CASE WHEN bound = 'L' THEN temperature END) )) * (MAX(CASE WHEN bound = 'U' THEN decrease_capacity END)-MAX(CASE WHEN bound = 'L' THEN decrease_capacity END)) + MAX(CASE WHEN bound = 'L' THEN decrease_capacity END)
                                END
       END
FROM   T2