【问题标题】:Select consecutive rows under a certain value in MySQL在MySQL中选择某个值下的连续行
【发布时间】:2019-04-10 19:15:18
【问题描述】:

选择连续行,列低于某个值

我有一个包含以下数据的表格:

crashID     crash
-----------------------
1           189
2           144
3           8939        
4           748
5           988
6           102
7           392
8           482
9           185
10          101

我想选择崩溃值低于某个阈值的最长连续行。假设这个例子是 500。

如何在单个 MySQL 查询中执行此操作? (v8.0.1)

期望的输出是这样的:

crashID     crash
------------------
6           102
7           392
8           482
9           185
10          101

【问题讨论】:

  • 你用的是什么版本的mysql?
  • 如何定义连续的? mysql没有记录的本机“顺序”。您首先必须根据条件(可以是 crashID)对它们进行排序
  • 是的,连续 crashID

标签: mysql sql group-by mysql-8.0


【解决方案1】:

您可以尝试使用间隙和孤岛方法来解决它,假设每次崩溃 lte 500 都是一个孤岛,然后找到最大的孤岛:

SET @threshold = 500;
WITH cte1 AS (
    SELECT
        crashID,
        CASE WHEN crash <= @threshold THEN 1 ELSE 0 END AS island,
        ROW_NUMBER() OVER (ORDER BY crashID) rn1,
        ROW_NUMBER() OVER (PARTITION BY CASE WHEN crash <= @threshold THEN 1 ELSE 0 END ORDER BY crashID) rn2
    FROM t
), cte2 AS (
    SELECT MIN(crashID) AS fid, MAX(crashID) AS tid
    FROM cte1
    WHERE island = 1
    GROUP BY rn1 - rn2
    ORDER BY COUNT(*) DESC
    LIMIT 1
)
SELECT *
FROM t
WHERE crashID BETWEEN (SELECT fid FROM cte2) AND (SELECT tid FROM cte2);

DB Fiddle

【讨论】:

【解决方案2】:

这是一种方法,适用于旧版本的 MySQL... 此解决方案假定第一名没有平局...

SELECT m.* 
  FROM my_table m
  JOIN 
     ( SELECT MIN(crash_id) range_start
            , MAX(crash_id) range_end
         FROM 
            ( SELECT x.*
                   , CASE WHEN FLOOR(crash/500) * 500 = 0 AND @prev = FLOOR(crash/500) * 500 THEN @i:=@i ELSE @i:=@i+1 END i
                   , @prev:=FLOOR(crash/500)*500 prev 
                FROM my_table x
                   , (SELECT @prev:=null,@i:=0) vars 
               ORDER 
                  BY crash_id
            ) a
        GROUP
           BY i
        ORDER
           BY COUNT(*) DESC LIMIT 1
     ) n
    ON m.crash_id BETWEEN n.range_start AND n.range_end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-23
    • 2015-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    相关资源
    最近更新 更多