今天因为业务需要,要从一个表中取不大于录入值的最大值,即有一张表,里面有一个因子,是一些等级,针对每个等级,都有一个比率,本来录入的值一定是和等级相等的,现在用户提出,要支持录入一些不是标准的等级的值,可以按照一定的规则,取小于或等于录入的等级的最大等级的比率。这个是简化了的业务逻辑,为了说明这个问题,把这个问题尽量简化了说,提供一个思路,供大家讨论,欢迎大拿帮忙提供更好的方法
第一步,先建立一张表,我们先忽略一些其他的问题,比如建立索引等等,只关注具体的问题。
假设在表中已经存在了下面这样的数据:
+-------div------rate-------+
|---------0----------1.00-------+
|---------30---------1.10-------+
|---------50---------1.20-------+
|---------90---------1.30-------+
从表中可以看出当p落在不同的区间是的取值:
当0<=p<30时,应该取0对应的比率;
当30<=p<50时,应该取30对应的比率;
当50<=p<90时,应该取50对应的比率;
当90<=p时,应该取90对应的比率。
我是这样分析的:先用录入的值p减去每一个divisor,并作为一个新的列,即使用下面的查询语句:
注:这里的p会从其他地方取得,在执行sql的时候就是具体的值了。
这样的话,就能求出来p和div的差了,就在这个差上做文章(这个文章不出轨 :wink: )!
针对一些特殊的录入值p,列举一些值的话,就会出现下面的这种情况
[table]
|序号|div|p=0|p=10|p=30|p=40|p=60|p=90|p=100|
|1|0|[color=red]0[/color]|[color=red]10[/color]|30|40|60|90|100|
|2|30|-30|-20|[color=red]0[/color]|[color=red]10[/color]|30|60|70|
|3|50|-50|-40|-20|-10|[color=red]10[/color]|40|50|
|4|90|-90|-80|-60|-50|-30|[color=red]0[/color]|[color=red]10[/color]|
[/table]
可以从这些数据中看到所取到的每个div,对应的p-div,都是取的差是最小的非负数,这就是突破点了。
再把这个问题分解一下,就是变成了取一个表的最小的非负数了。
可以用下面的SQL:
经过上面一步,已经知道小于或等于录入值p的最大的div,剩下的就是从p_rate 表中取该div对应的rate了。把SQL写出来就是这样的:
再提供一个写法,和上面的逻辑一模一样,只是换了一个写法,这种做法可能更多的用在一些字段比较多的报表的SQL中,在这儿体现不出它的优势
再次的,无比热切的欢迎更好的思路和方法 :arrow: ,最好是一个自带的function就能解决问题 :wink:
第一步,先建立一张表,我们先忽略一些其他的问题,比如建立索引等等,只关注具体的问题。
create table p_rate
(
div number(2) not null,
rate number(10,2) not null,
PRIMARY KEY (div)
)
假设在表中已经存在了下面这样的数据:
+-------div------rate-------+
|---------0----------1.00-------+
|---------30---------1.10-------+
|---------50---------1.20-------+
|---------90---------1.30-------+
从表中可以看出当p落在不同的区间是的取值:
当0<=p<30时,应该取0对应的比率;
当30<=p<50时,应该取30对应的比率;
当50<=p<90时,应该取50对应的比率;
当90<=p时,应该取90对应的比率。
我是这样分析的:先用录入的值p减去每一个divisor,并作为一个新的列,即使用下面的查询语句:
select div,p-div from p_rate
注:这里的p会从其他地方取得,在执行sql的时候就是具体的值了。
这样的话,就能求出来p和div的差了,就在这个差上做文章(这个文章不出轨 :wink: )!
针对一些特殊的录入值p,列举一些值的话,就会出现下面的这种情况
[table]
|序号|div|p=0|p=10|p=30|p=40|p=60|p=90|p=100|
|1|0|[color=red]0[/color]|[color=red]10[/color]|30|40|60|90|100|
|2|30|-30|-20|[color=red]0[/color]|[color=red]10[/color]|30|60|70|
|3|50|-50|-40|-20|-10|[color=red]10[/color]|40|50|
|4|90|-90|-80|-60|-50|-30|[color=red]0[/color]|[color=red]10[/color]|
[/table]
可以从这些数据中看到所取到的每个div,对应的p-div,都是取的差是最小的非负数,这就是突破点了。
再把这个问题分解一下,就是变成了取一个表的最小的非负数了。
可以用下面的SQL:
select min(div)
from (select div,p-div as pd from p_rate)
where pd>=0
经过上面一步,已经知道小于或等于录入值p的最大的div,剩下的就是从p_rate 表中取该div对应的rate了。把SQL写出来就是这样的:
select rate
from p_rate
where div = (select min(div)
from (select div,p-div as pd from p_rate)
where pd>=0)
再提供一个写法,和上面的逻辑一模一样,只是换了一个写法,这种做法可能更多的用在一些字段比较多的报表的SQL中,在这儿体现不出它的优势
with tmp as
(select div,p-div as pd
from p_rate)
select rate
from p_rate
where div = (select min(div) from tmp where pd>=0)
再次的,无比热切的欢迎更好的思路和方法 :arrow: ,最好是一个自带的function就能解决问题 :wink: