SQL代码计算表中两行之间给定值的比例值

时间:2019-01-27 11:22:58

标签: sql

我对SQL非常陌生。我只能做Excel宏。 我有储水箱容积表,其ID,高度和容积如下所示

Id  Height  Volume
1     0          0
2     1       1000
3     2       1950
4     3       3050
5     4       4020  
6     5       5000

我需要一个sql代码来计算实际罐高为3.5时的比例值。 答案应该是(((4020-3050)/(4-3))*(3.5-3))+3050 = 3535

3 个答案:

答案 0 :(得分:0)

没有给出DBMS,但是此答案适用于MySql,并且基于所谓的Windows函数,希望它也可以在其他DBMS上使用。

内部子查询在同一行上创建一个高度,高度,前一行高度,体积和前一行体积的表。这样就可以选择正确的行,并根据给定的高度对体积进行线性插值

SELECT DISTINCT ((volume - prev_volume)/(height - prev_height)) * (@given_height - prev_height) + prev_volume AS calculated_volume
FROM (SELECT height, 
             LAG(height, 1) OVER w AS prev_height,
             volume,
             LAG(volume, 1) OVER w AS prev_volume
      FROM volume
      WINDOW w AS (ORDER BY height ASC)) AS t
WHERE @given_height BETWEEN prev_height and height

答案 1 :(得分:0)

这是另一种解决方案,它使用标准的ANSI sql,并且不依赖于窗口函数,因此应该适用于大多数RDBMS /版本。

原理是使用子查询查找给定高度附近最接近的记录的ID,然后在外部查询中进行计算。您需要将?替换为要为其计算体积的高度。

SELECT
    (tsup.volume - tinf.volume)
        / (tsup.height - tinf.height)
        * (? - tinf.height) 
        + tinf.volume
    as regression
FROM
    (
        SELECT t.*
        FROM mytable t
        WHERE id = (SELECT MIN(id) FROM mytable WHERE height > ?) 
    ) tsup
    CROSS JOIN (
        SELECT t.*
        FROM mytable t
        WHERE id = (SELECT MAX(id) FROM mytable WHERE height < ?)
    ) tinf

这里是a MySQL 5.7 DB fiddle

SET @search = 3.5;

SELECT
    (tsup.volume - tinf.volume)/(tsup.height - tinf.height)*(@search - tinf.height) + tinf.volume regression
FROM
    (
        SELECT t.*
        FROM mytable t
        WHERE id = (SELECT MIN(id) FROM mytable WHERE height > @search) 
    ) tsup
    CROSS JOIN (
        SELECT t.*
        FROM mytable t
        WHERE id = (SELECT MAX(id) FROM mytable WHERE height < @search)
    ) tinf;
| regression |
| ---------- |
| 3535       |

答案 2 :(得分:0)

您想要下一个最小值和最大值。您可以使用:

(select t.*
 from t
 where t.height <= 3.5
 order by t.height desc
 fetch first 1 row only
) union all
(select t.*
 from t
 where t.height >= 3.5
 order by t.height asc
 fetch first 1 row only
) 

使用此信息,您可以进行所需的计算:

select (case when min(height) = max(height) 
 -- exact match
             then min(volume)
             else (min(volume +
                   (max(volume) - min(volume)) / (max(height - min(height)) * (3.5 - min(height)
                 )
        end) as interpolated_volume
from ((select t.*
       from t
       where t.height <= 3.5
       order by t.height desc
       fetch first 1 row only
      ) union all
      (select t.*
       from t
       where t.height >= 3.5
       order by t.height asc
       fetch first 1 row only
      ) 
     ) t;

这假定体积随高度增加-在这种情况下,这似乎非常合理。可以针对其他情况调整此代码。

请注意,这使用标准的SQL语法元素。一些数据库的语法略有不同。