I have a question about SQL.
I have the following sample table called Records
:
record_id | subject | start_timestamp | end_timestamp | interval |
---|---|---|---|---|
2 | Start Product 2 | 2021-04-21T16:22:39 | 2021-04-21T16:23:40 | 0.97 |
3 | error 1 | 2021-04-21T16:25:44 | 2021-04-21T16:25:54 | 10.0 |
4 | End Product 2 | 2021-04-21T16:30:13 | 2021-04-21T16:30:14 | 0.97 |
5 | Start Product 1 | 2021-04-21T16:35:13 | 2021-04-21T16:35:13 | 0.6 |
6 | End Product 1 | 2021-04-21T16:36:13 | 2021-04-21T16:36:13 | 0.45 |
First I select all the items that have start
in there subject with and are not in the table BackupTO
(for now the table BackupTO
is not important):
SELECT Records.record_id, Records.start_timestamp, Records.interval FROM Records LEFT JOIN BackupTO ON BackupTO.record_id = Records.record_id WHERE BackupTO.record_id IS NULL AND Records.log_type = 1 AND Records.subject LIKE '%start%'
When I ran this we get:
record_id | start_timestamp | interval |
---|---|---|
2 | 2021-04-21T16:22:39 | 0.97 |
5 | 2021-04-21T16:35:13 | 0.6 |
Oke, all good now comes my question, I fetch this in Python and loop through the data, first I calculate the product number based on the interval
with:
product = round(result[2] / 0.5)
So a interval of 0.97 is product 2, and a interval of 0.6,0.45 is product 1, all great!
So I know record_id 2
is product 2 and I want to execute a sql query thats returns all items starting from record_id 2
untils its find a items that has %end%2
in its name (the 2 is for product 2, could also be product 1).
For example its finds Start Product 2
I get a list with record_id
3 and 4.
I want to get all items from the start until end.
So it gets me a list like this, this are all the items found under Start Product 2
until %end%2
was found. For product 1, it just would return just record_id 6
, because there is nothing between the start and stop.
record_id | start_timestamp | interval |
---|---|---|
3 | 2021-04-21T16:22:39 | 10.0 |
4 | 2021-04-21T16:35:13 | 0.97 |
I tried OFFSET and FETCH, but I couldnt get it to work, somebody that could help me out here?
Advertisement
Answer
Use your query as a CTE and join it to the table Records
.
Then with MIN()
window function find the record_id
up to which you want the rows returned:
WITH cte AS ( SELECT r.* FROM Records r LEFT JOIN BackupTO b ON b.record_id = r.record_id WHERE b.record_id IS NULL AND r.log_type = 1 AND r.subject LIKE '%start%' ) SELECT * FROM ( SELECT r.*, MIN(CASE WHEN r.subject LIKE '%end%' THEN r.record_id END) OVER () id_end FROM Records r INNER JOIN cte c ON r.record_id > c.record_id WHERE c.record_id = ? ) WHERE COALESCE(record_id <= id_end, 1)
Change ?
to 2
or 5
for each case.
If you have the record_id
s returned by your query, it is simpler:
SELECT * FROM ( SELECT r.*, MIN(CASE WHEN r.subject LIKE '%end%' THEN r.record_id END) OVER () id_end FROM Records r WHERE r.record_id > ? ) WHERE COALESCE(record_id <= id_end, 1)
See the demo.