-1

I have a SQL questions: I want to populate rank for each record as a next up number. However I want to keep the rank same for records for which the adjust values are not same.

Sample data :

# | value | date1      | * rank (expected)
--+-------+------------+-------
1 | A     | 05/01/2020 |    1
1 | A     | 05/02/2020 |    2
1 | A     | 05/03/2020 |    3
1 | B     | 05/04/2020 |    3
1 | A     | 05/05/2020 |    3
1 | A     | 05/06/2020 |    4
1 | A     | 05/07/2020 |    5
1 | A     | 05/08/2020 |    6
1 | B     | 05/09/2020 |    6
1 | A     | 05/10/2020 |    6
1 | A     | 05/11/2020 |    7

I am looking for best way to populate the 4th column based on the first three.

2 Answers2

1

You don't provide a good explanation for the logic. But you seem to want to not count "B"s and the "A" on the next row.

This can be phrased as the following equation:

  • The row number minus
  • twice the number of Bs up to that row (to get the following row as well)
  • plus 1 if the row is B (because we just over subtracted the next row).

This can be implemented as:

select t.*,
       (row_number() over (partition by num order by date1) -
        2 * count(*) filter (where value = 'B') over (order by date1) +
        (value = 'B')::int
       )
from t
order by num, date1;

Here is a db<>fiddle.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
0

I think you want to increment the counter only when the value on the current row is the same as in the previous row. You can do this with lag() and a cumulative sum():

select id, value, date1,
    sum(case when lag_value <> value then 0 else 1 end) as rnk
from (
    select t.*,
        lag(value) over(order by date1) as lag_value
    from mytable t
)
GMB
  • 216,147
  • 25
  • 84
  • 135