MySQL - 在匹配条件之后返回具有 n 个连续记录的所有记录

Posted

技术标签:

【中文标题】MySQL - 在匹配条件之后返回具有 n 个连续记录的所有记录【英文标题】:MySQL - return all records that have n amount of consecutive records after that match criteria 【发布时间】:2020-06-09 18:38:50 【问题描述】:

mysql v5.5

嗨 - 我需要从一个简单的表中创建一个选择查询,它返回所有行,这些行之后有一定数量的连续行,这些行被标记为可用。

示例表数据如下:

id   Slot    Available
0    5.00pm  1
1    5.10pm  1   
2    5.20pm  1
3    5.30pm  0
4    5.40pm  1
5    5.50pm  1
6    6.00pm  1
7    6.10pm  1

我有一个变量来确定所需的插槽数。

因此,例如,如果变量为 3,我需要结果返回所有有 2 个连续可用插槽的插槽。

本例中的期望结果是:

id   Slot    Available
0    5.00pm  1
4    5.40pm  1
5    5.50pm  1

我们将不胜感激。

(我不是专业开发人员,所以请温柔:))

非常感谢

【问题讨论】:

您能否澄清或提供更多示例? 1) 什么是“2 个连续可用的插槽”?我看到集合中的所有插槽都是连续的,并且排序顺序中有提供。 2)为什么恰好是2个连续的插槽,“连续”是什么意思? 3) 为什么在所需的解决方案中返回 0,4,5 而不是 0,1,7?有什么区别? 见meta.***.com/questions/333952/… 【参考方案1】:

我确信有一种方法可以用 SQL 做你想做的事。我有一个您可以使用的存储过程示例。

DELIMITER //

DROP PROCEDURE IF EXISTS GetTimeSlots;

CREATE PROCEDURE GetTimeSlots(NoOfSlots int)
BEGIN

    declare finished bool default false;

    -- stores id, slot and available from the cursor
    declare v_id int;
    declare v_slot text;
    declare v_available int;

    -- stores how many slots were found consecutively
    declare v_slotsfound int;

    -- loop through all available records
    declare c cursor for
    select id, slot, available from test where available = 1;

    declare continue handler for not found
    set finished = true;

    -- create empty table to store slots we find
    drop temporary table if exists tmp;
    create temporary table tmp
    select * from test where 1=2;

    open c;
    looper: loop
        fetch c into v_id, v_slot, v_available;
        if finished then
            leave looper;
        end if;

        select sum(case
                   when available then 1
                   else 0
                   end) into v_slotsfound
        from (
            -- list out as many slots you need
            -- outer query will total up the # of available slots
            select available from test where id >= v_id
            order by id
            limit NoOfSlots
        ) t;

        -- if # of available slots equals how many you want, store data
        -- in temporary table
        if v_slotsfound = NoOfSlots then
            insert into tmp values (v_id, v_slot, v_available);
        end if;

    end loop looper;
    close c;

    -- output the results
    select * from tmp;
    drop temporary table if exists tmp;

END //

DELIMITER ;

运行它

mysql> call gettimeslots(3);
+------+--------+-----------+
| id   | slot   | available |
+------+--------+-----------+
|    0 | 5.00pm |         1 |
|    4 | 5.40pm |         1 |
|    5 | 5.50pm |         1 |
+------+--------+-----------+

如果你想要 2 个连续的插槽:

mysql> call gettimeslots(2);
+------+--------+-----------+
| id   | slot   | available |
+------+--------+-----------+
|    0 | 5.00pm |         1 |
|    1 | 5.10pm |         1 |
|    4 | 5.40pm |         1 |
|    5 | 5.50pm |         1 |
|    6 | 6.00pm |         1 |
+------+--------+-----------+

如果你想要 4 个连续的插槽:

mysql> call gettimeslots(4);
+------+--------+-----------+
| id   | slot   | available |
+------+--------+-----------+
|    4 | 5.40pm |         1 |
+------+--------+-----------+

使用的数据

create table test (id int, slot text, avaialable int);
insert into test values
(0,    '5.00pm', 1)
,(1,    '5.10pm',  1)   
,(2,    '5.20pm',  1)
,(3,    '5.30pm',  0)
,(4,    '5.40pm',  1)
,(5,    '5.50pm',  1)
,(6,    '6.00pm',  1)
,(7,    '6.10pm',  1);

【讨论】:

太棒了,谢谢!最后一件事,因为我完全不知道它是如何工作的,所以我只需要始终包含第一个插槽,而不管连续插槽如何。请你指出我正确的方向。再次感谢您 你能用一个例子解释你的意思@user1830274吗?您可以编辑您的问题并添加示例。告诉我你想要什么。 您提供的代码完美运行,我只需要始终返回第一行(id 0),只要它被标记为可用。 哦,我明白了。在select * from tmp; 行上方,输入insert into tmp select * from test where available = 1 limit 1; 这将在所有其他行之上添加第一个可用时隙。为了更好地衡量,您还应该将 select * from tmp; 更改为 select * from tmp order by id 谢谢,非常感谢

以上是关于MySQL - 在匹配条件之后返回具有 n 个连续记录的所有记录的主要内容,如果未能解决你的问题,请参考以下文章

匹配列表中的一个元素,然后返回它之前的“n”个元素和它之后的“m”个元素

MySQL插入查询如果条件匹配在插入触发器之后

Java数组怎样按条件分离为N个小数组?

bzoj2384[Ceoi2011]Match 特殊匹配条件的KMP+树状数组

最多具有K个元素的最大连续子数组

mysql返回最大n个具有相同值的行