选择多行,其中值的差异大于x%

unguejic  于 2021-08-09  发布在  Java
关注(0)|答案(2)|浏览(304)

我面临以下问题。。。给出以下数据:表:投票

=========
  value
=========
   10
   25
   38
   90
   92
   93
   98
   100
   120

如果下一个值和以前接受的值之间的差值大于第一个值的10%,我只返回值:

if abs(int(a)-int(b))*100/int(a) < 10:
  return True

所以最后的列表应该是(我在方括号中加了%的差异):

==========
  result
==========
   10 ()
   25 (150%)
   38 (52%)
   90 (136%)
   100 (11%)
   120 (20%)

查询还应首先对这些值进行排序。
我可以用代码来实现它(如上所示),但是我没有机会接近直接查询。
mysql版本8.0.19

fgw7neuy

fgw7neuy1#

您没有提到您使用的是哪个版本的mysql,所以我假设它是一个现代版本(8.x)。你可以用 LAG() . 例如:

select
  concat('', value,
    case when prev_value is null then '' 
       else concat('', 100 * (value - prev_value) / prev_value, '%')
    end
  ) as result
from (
  select
    value,
    lag(value) over (order by value) as prev_value
  from t
) x
where prev_value is null or value > prev_value * 1.1
order by value
juzqafwq

juzqafwq2#

在mysql 8.0中,您可以使用 lag() . 假设您想按 value ,即:

select value
from (
    select
        value,
        lag(value, 1, 0) over(order by value) lag_value
    from mytable t
) t
where value > lag_value * 1.10

如果要使用不同的排序列,则可以更改 order by 子句使用相关列。
在早期版本中,一个选项是相关子查询:

select value
from mytable t
where value > 1.10 * coalesce(
    (
        select t1.value 
        from mytable t1 
        where t1.value < t.value
        order by t1.value desc
        limit 1
    ),
    0
)

要在此处使用另一个排序列,您需要更改 where 条款和 order by 子查询的子句。
另一方面,如果您想根据与先前所选行的比率来选择下一行,那么这是另一个问题。您需要某种迭代过程:在sql中,一种方法是递归查询:

with 
    data as (
        select value, row_number() over(order by value) rn
        from mytable t
    ) d,
    cte as (
        select 1 is_valid, value, rn from data where rn = 1
        union all 
        select 
            (d.value > 1.1 * c.value),
            case when d.value > 1.1 * c.value then d.value else c.value end,
            d.rn
        from cte c
        inner join data d on d.rn = c.rn + 1
    )
    select value from cte where is_valid order by value

查询枚举这些值,然后依次遍历数据集,同时跟踪最后选定的值,并对应出现在最终结果集中的记录设置标志。

相关问题