【问题标题】:Calculate Rate based on distance range根据距离范围计算速率
【发布时间】:2013-10-07 05:26:17
【问题描述】:

我一直在为一个具有以下表格结构的项目工作

开始 |结束 |速度 ------------------ 1 | 50 | 10 51 | 100 | 20 101 | 150 | 40 151 | 200 | 80 201 | 0 |100

这里最后一条记录表示 200 到无限值的比率为 100

这里我必须根据用户给出的开始和结束值来计算总费率

我在 mysql 中尝试了以下查询,输入 start - 30, end - 170

SELECT SUM((end+1 - start) * amount) 
FROM table 
WHERE start > 30
AND end < 170

只给出第二个 和第三条记录值相加,那么我必须分别查询第一条和最后一条记录。

如何在单个查询中实现这一点?

【问题讨论】:

  • 我的理解正确吗,随着起点的上升,利率也会上升,所以如果你从 30 开始到 170,那么数学将是 (20*10)+(49*20)+(49*40)+(19*80)
  • 请分享实际计算费率的公式...
  • 你是对的,但稍加修正,数学将是
    (20*10)+(50*20)+(50*40)+(20*80)前>
  • 根据您的距离计算方式,您可能希望移动到专属上限。这是因为有 50 到 51 之间的值 - 请参阅 this blog post 以获取与时间戳相关的示例。在具有递归 CTEs/a ROW_NUMBER() 函数的 RDBMS 中,我只存储范围的 start,并将此表组装为视图。

标签: php mysql sql range


【解决方案1】:

假设我们声明了以下两个参数:

set @start = 30, @end = 170;

首先要获取您范围内的行(重叠),我们会这样做 (SQL Fiddle):

select start, end
from Table1
where start <= @end OR end >= @start

然后我们按摩第一行和最后一行的范围的开始和结束。基本上,我们将范围的第一部分设置为@start,将范围的第二部分设置为@end (SQL Fiddle):

select CASE WHEN @start > start THEN @start ELSE start END AS start, 
    CASE WHEN @end < end THEN @end ELSE end END AS end
from Table1
where start <= @end OR end >= @start

然后我们可以将这两个case表达式相减得到距离。如果你想要 inclusive 距离,别忘了加 1 (SQL Fiddle):

select CASE WHEN @end < end THEN @end ELSE end END - CASE WHEN @start > start THEN @start ELSE start END + 1 AS dist
from Table1
where start <= @end OR end >= @start

乘以比率。这次不要忘记括号,因为乘法优先(SQL Fiddle):

select rate * (CASE WHEN @end < end THEN @end ELSE end END - CASE WHEN @start > start THEN @start ELSE start END + 1)
from Table1
where start <= @end OR end >= @start

最后,在整个表达式周围加上 SUM 以将其全部加起来 (SQL Fiddle):

select SUM(rate * (CASE WHEN @end < end THEN @end ELSE end END - CASE WHEN @start > start THEN @start ELSE start END))
from Table1
where start <= @end OR end >= @start

【讨论】:

  • 我们必须使用 where 子句中的 or 条件,然后条件必须检查结束值 0 作为无限,开始和结束值可能会有所不同,如果开始 - 230 和结束 270 那么计算应该为 40*100=400
  • @Kanagu 如果您对数据方案有任何控制权,我建议您使用NULL 而不是0 来识别无穷大。然后,您可以强制执行约束 end &gt;= start OR start IS NULL OR end IS NULL 并通过对 NULL 进行一些额外的调整来使数学变得有意义。
【解决方案2】:

基于lc.的算法,你可以在MySQL中运行这个:

SET @start = 30, @end = 170;

SELECT
  sum(rate * (least(`end`, @end) - greatest(start, @start) + 1)) TotalRate
FROM Table1
WHERE @end >= start OR @start <= `end`

【讨论】:

    【解决方案3】:

    根据@lc的建议,以下查询符合我的预期

        SET @start=30, @end=170;
        SELECT SUM(rat*(CASE WHEN @end < end or end=0 THEN @end ELSE end END - CASE WHEN @start > start THEN @start ELSE start-1 END)) as price
        FROM rate
        WHERE start <= @end and (end >= @start or end=0)
    

    并且此查询满足以下所有条件

    当 start-60、end-140 时,数学将是 (40*20)+(40*40)=2400

    当 start-230,end 270 那么数学将是 (40*100)=400

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 2019-04-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多