Выберите последовательные строки под определенным значением в MySQL - PullRequest
0 голосов
/ 07 ноября 2018

Выбор последовательных строк со столбцом под определенным значением

У меня есть таблица со следующими данными:

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

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Вот один способ, для более старых версий 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;
0 голосов
/ 07 ноября 2018

Вы можете попытаться решить эту проблему, используя подходы с пробелами и островами, предположим, что каждая авария - это остров, а затем найдите самый большой остров:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...