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”个元素