如何获得任何连续范围内的最大值

How to get the biggest value in any consecutive range

考虑无符号整数索引列中的以下值:

1
2
3
3
2
4
6
8
9

对于任何提供的数字,我想获得其连续范围内的最大值(当存在下一个连续数字时继续前进)。

例如,假设我们得到的输入是234 的连续值确实存在于列表中(无论它们的顺序如何),但 5 不存在;因此我们的连续范围将是 2,3,4;因此期望值将是 4:这个连续范围内的最大值;提供 134 中的任何一个后,还应产生 4。因此:

input           expected output
-------------------------------
1,2,3,4                       4  -- any value of the input yields 4
5                             5  -- the input value doesn't even exist in the list
6                             6  -- it's the only value
7                             7  -- the input value doesn't even exist in the list
8,9                           9

那么,如何使用MySQL获得任何连续范围内的最大值?

这可能是一个间隙隔离问题,可能需要使用window函数来解决,CTE递归来解决。

首先,我们可以尝试使用CTE递归生成器调用startnum范围从最小数到最大的数据(来自我们的样本是19),因为他们之间少了一些数字。

下一步我们可能会计算 grp 即 gap-and-island 问题特征逻辑。

逻辑可能如下。

continuous(overlapping) data is that a set (continuous range of sequence) - (values ​​based on a certain order of conditions sequence) yields the same grouping.

所以我们可以使用

  • 序列的连续范围:startNum
  • 取值按一定顺序:dense_rankwindow函数.

使用这个逻辑我们可能会得到一个 grp 列作为 sqlfiddle

查询#1

WITH RECURSIVE cte AS(
   SELECT MIN(val) startNum, MAX(val) endNum
   FROM T
   UNION ALL
   SELECT startNum + 1,endNum
   FROM cte
   WHERE startNum + 1 <= endNum
)
SELECT GROUP_CONCAT(DISTINCT startNum) input,
       MAX(startNum) 'expected output'
FROM (
  SELECT val,
     startNum ,
     startNum - cast(dense_rank() OVER(ORDER BY val)as signed) grp
  FROM cte t1
  LEFT JOIN T t2
  ON t1.startNum = t2.val
) t1
GROUP BY grp
ORDER BY 2;
input expected output
1,2,3,4 4
5 5
6 6
7 7
8,9 9

View on DB Fiddle

使用递归 CTE:

WITH RECURSIVE cte AS (
  SELECT x FROM tablename WHERE x = ?
  UNION 
  SELECT t.x
  FROM tablename t INNER JOIN cte c
  ON t.x = c.x + 1
)
SELECT COALESCE(MAX(x), ?) x FROM cte;

参见demo

或者,使用 DENSE_RANK() window 函数:

SELECT COALESCE(MAX(CASE WHEN x = rn THEN x END), ?) x
FROM (
  SELECT x, DENSE_RANK() OVER (ORDER BY x) + ? rn
  FROM tablename
  WHERE x > ? AND EXISTS (SELECT * FROM tablename WHERE x = ?)
) t

参见demo

? 替换为您想要的 input 值。