I have the following data (fiddle),
id | datec | event |
---|---|---|
1 | 2022-09-19 12:16:38 | EVENTA |
2 | 2022-09-19 12:16:38 | A |
3 | 2022-09-19 12:21:08 | B |
4 | 2022-09-19 12:21:12 | EVENTD |
5 | 2022-09-19 12:25:18 | C |
6 | 2022-09-19 12:25:18 | D |
7 | 2022-09-19 12:25:28 | E |
8 | 2022-09-19 12:25:29 | F |
9 | 2022-09-19 12:25:38 | EVENTA |
10 | 2022-09-19 12:25:39 | G |
11 | 2022-09-19 12:25:40 | H |
12 | 2022-09-19 12:25:48 | I |
13 | 2022-09-19 12:27:18 | EVENTD |
14 | 2022-09-19 12:29:08 | J |
I can't figure out how to select values between two others, but in a specific order. Only events between EVENTA and EVENTD should be returned, in that order.
So that results should be the rows with id 1 to 4 and 9 to 13
Tried to do something like the following, but it is giving me id 1,4,9 and 13 omitting what is between them.
SELECT id, datec, event
FROM table1
WHERE event BETWEEN 'EVENTA' AND 'EVENTD';
I then tried to use this,
SELECT id, datec, event
FROM table1
WHERE (id BETWEEN (SELECT id
FROM table1
WHERE event BETWEEN 'EVENTA' AND 'EVENTD'
LIMIT 1)
AND (SELECT id
FROM table1
WHERE event BETWEEN 'EVENTA' AND 'EVENTD'
LIMIT 1,1))
OR (id BETWEEN (SELECT id
FROM table1
WHERE event BETWEEN 'EVENTA' AND 'EVENTD'
LIMIT 2,1)
AND (SELECT id
FROM table1
WHERE event BETWEEN 'EVENTA' AND 'EVENTD' LIMIT 3,1));
And it gives me the results but I have many rows in my table.
Can please someone guide me on how to repeat this till the end as i'm sure there is a way to do this but i can't figure out how?
Regards,
pierre
Here's one approach:
At this point you should note that this ranking value we generated, assumes value 0 when there's not yet an EventD in our armed_event partition. And it gets value 1 when the first EventD is found, till the successive EventD.
So you can just filter accordingly inside a WHERE
clause, when this ranking value is either 0 or is 1 and event is exactly "EventD".
WITH cte AS (
SELECT *, SUM(`event`='EVENTA') OVER(ORDER BY datec, id) AS armed_events,
SUM(`event`='EVENTD') OVER(ORDER BY datec, id) AS disarmed_events
FROM Table1
), cte2 AS (
SELECT *, DENSE_RANK() OVER(PARTITION BY armed_events ORDER BY disarmed_events) -1 AS rn
FROM cte
)
SELECT `id`, `datec`, `event`
FROM cte2
WHERE rn = 0 OR (rn = 1 AND `event` = 'EVENTD')
ORDER BY id
Output:
id | datec | event |
---|---|---|
1 | 2022-09-19 12:16:38 | EVENTA |
2 | 2022-09-19 12:16:38 | A |
3 | 2022-09-19 12:21:08 | B |
4 | 2022-09-19 12:21:12 | EVENTD |
9 | 2022-09-19 12:25:38 | EVENTA |
10 | 2022-09-19 12:25:39 | G |
11 | 2022-09-19 12:25:40 | H |
12 | 2022-09-19 12:25:48 | I |
13 | 2022-09-19 12:27:18 | EVENTD |
Check the demo here.
Note: The last ORDER BY
clause is not necessary. It's there just for visualization purposes.