On this post, I will discuss the exact reverse of that.
Given the following data:
CREATE TABLE y ("id" int, "val" varchar(1)) ; INSERT INTO y ("id", "val") VALUES (1, 'a'), (4, 'b') ; CREATE TABLE x ("id" int) ; INSERT INTO x ("id") VALUES (1), (2), (3), (4), (5) ; with z as ( select x.id, y.val from x left join y on y.id = x.id ) select * from z order by id ;
| ID | VAL | --------------- | 1 | a | | 2 | (null) | | 3 | (null) | | 4 | b | | 5 | (null) |
Requirement is to cluster those gaps together:
| ID | VAL | ------------ | 1 | a | | 2 | a | | 3 | a | | 4 | b | | 5 | b |
The easiest way to solve that is to use windowing function, i.e. use first_value on each group. First thing first, we must devise a way to group those gaps together. We can do that by counting over the id's order. COUNT doesn't count nulls, hence COUNT will be able to group nulls to a previous non-null, COUNT will maintain the same count as long as it is encountering nulls. To illustrate:
with z as ( select x.id, y.val, count(y.val) over(order by x.id ) as grp from x left join y on y.id = x.id ) select * from z order by id ;
Output:
| ID | VAL | GRP | --------------------- | 1 | a | 1 | | 2 | (null) | 1 | | 3 | (null) | 1 | | 4 | b | 2 | | 5 | (null) | 2 |
Now that we designated a grouping number for related data, getting the first value among the group shall just be a simple undertaking, use first_value from the partition of grp
with z as ( select x.id, y.val, count(y.val) over(order by x.id ) as grp from x left join y on y.id = x.id ) select id, val, grp, first_value(val) over(partition by grp order by id) from z;
Output:
| ID | VAL | GRP | FIRST_VALUE | ----------------------------------- | 1 | a | 1 | a | | 2 | (null) | 1 | a | | 3 | (null) | 1 | a | | 4 | b | 2 | b | | 5 | (null) | 2 | b |
No comments:
Post a Comment