Query: SELECT (row_number() OVER ()) as grp, * from tbl
Edit: the rows below are returned by a pgrouting shortest path function and it does have a sequence.
seq grp id
1 1 8
2 2 3
3 3 2
4 4 null
5 5 324
6 6 82
7 7 89
8 8 null
9 9 1
10 10 2
11 11 90
12 12 null
How do I make it so that the grp
column is only incremented after a null
value on id
- and also keep the same order of rows
seq grp id
1 1 8
2 1 3
3 1 2
4 1 null
5 2 324
6 2 82
7 2 89
8 2 null
9 3 1
10 3 2
11 3 90
12 3 null
CodePudding user response:
Using a cumulative SUM
aggregation is a possible approach:
SELECT
SUM( -- 2
CASE WHEN id IS NULL THEN 1 ELSE 0 END -- 1
) OVER (ORDER BY seq) as grp,
id
FROM mytable
- If the current (ordered!) value is
NULL
, then make it1
, else0
. Now you got a bunch of zeros, delimited by a 1 at eachNULL
record. If you'd summerize these values cumulatively, at eachNULL
record, the sum increased. - Execution of the cumulative
SUM()
using window functions
This yields:
0 8
0 3
0 2
1 null
1 324
1 82
1 89
2 null
2 1
2 2
2 90
3 null
As you can see, the groups start with the NULL
records, but you are expecting to end it.
This can be achieved by adding another window function: LAG()
, which moves the records to the next row:
SELECT
SUM(
CASE WHEN next_id IS NULL THEN 1 ELSE 0 END
) OVER (ORDER BY seq) as grp,
id
FROM (
SELECT
LAG(id) OVER (ORDER BY seq) as next_id,
seq,
id
FROM mytable
) s
The result is your expected one:
1 8
1 3
1 2
1 null
2 324
2 82
2 89
2 null
3 1
3 2
3 90
3 null
CodePudding user response:
You can count the amount of null
s in all the preceding rows:
select (select count(*) from tbl it where it.id is null and it.seq < t.seq order by seq), t.*
from tbl t
order by t.seq
Note that you need to define an ordering first by using order by
. You cannot preserve the order if there is none.