Suppose I have this table, named Table
+----+------+------+
| ID | Col1 | Col2 |
+----+------+------+
| 1 | A | 0 |
| 2 | B | 0 |
| 3 | C | 1 |
| 4 | A | 1 |
| 5 | D | 0 |
| 6 | A | 0 |
| 7 | F | 1 |
| 8 | H | 1 |
+----+------+------+
I want this result:
+----+------+------+
| ID | Col1 | Col2 |
+----+------+------+
| 3 | C | 1 |
| 4 | A | 1 |
| 7 | F | 1 |
+----+------+------+
That is:
- If
Col1
= A andCol2
= 1, take the corresponding row - If
Col1
= A andCol2
= 0, take the first row below it whereCol2
= 1
I tried something like
SELECT CASE
WHEN t.Col2 > 0
THEN t.Col2
WHEN t1.Col2 > 0
THEN t1.Col2
WHEN t2.Col2 > 0
THEN t2.Col2
FROM Table t
JOIN table t1 ON t.id - 1 = t1.id
JOIN table t2 ON t.id - 2 = t2.id
WHERE t.Col2 = 'A'
but it’s not quite what I was looking for. I couldn’t come up with any solution. What should I do?
Advertisement
Answer
Use window functions SUM() and MIN():
with
cte1 as (
select *, sum(case when col1 = 'A' and col2 = 0 then 1 else 0 end) over (order by id) grp
from tablename
),
cte2 as (
select *, min(case when col2 = 1 then id end) over (partition by grp order by id) next_id
from cte1
)
select id, col1, col2
from cte2
where (col1 = 'A' and col2 = 1) or (id = next_id)
See the demo.
Results:
> id | col1 | col2
> -: | :--- | ---:
> 3 | C | 1
> 4 | A | 1
> 7 | F | 1