Фильтровать сумму значений до достижения определенного порога

#postgresql

#postgresql

Вопрос:

DbFiddle

Застрял. Нужно ТАК 🙂

Рассмотрим следующее распределение значений.

 ID  CNT SEC SHOW(Bool)
1   10  1
2   1   1
3   25  1
4   1   1
5   2   1
6   10  1
7   50  2
8   90  2
  

Моя цель — фильтровать по sec , а затем

  • сортировка по cnt возрастанию,
  • сортировка по id возрастанию

а затем помечать / фильтровать все строки как show - false where cnt is < 5 и до тех sum cnt пор, пока число всех скрытых строк (show = false) не станет> = 5.

Таким образом, сумма всех «скрытых» строк никогда не может быть <5.

Ожидаемый результат для sec=1 :

 | id | cnt | cnt_sum | show  |
|----|-----|---------|-------|
| 2  | 1   | 1       | false |
| 4  | 1   | 2       | false |
| 5  | 2   | 4       | false |
| 1  | 10  | 14      | false | -- The sum of all hidden rows before this point is 4
| 6  | 10  | 24      | true  | -- The total of all hidden rows is now >= 5. 
| 3  | 25  | 49      | true  |
  

Ожидаемый результат для sec=2 :

 | id | cnt | cnt_sum | show  |
|----|-----|---------|-------|
| 7  | 50   | 50     | true  |
| 8  | 90   | 140    | true  |
  

Я уже могу сортировать значения и создавать суммы и т.д. Я не понял, как определить, как установить точку отсечения, когда «скрытие» не требуется.

Я уже делаю это в «клиентском коде» и хочу перенести его на sql.

Ответ №1:

Это LAG() поможет достичь того, чего вы хотите. Вы можете написать свой запрос, как показано ниже:

 with cte as (
SELECT
    id, cnt, sec,
    sum(cnt) over (partition by sec order by cnt,id) sum_
FROM
    tbl )
    
    select 
    id, cnt, sum_,
    case
    when sum_<5 or lag(sum_) over (partition by sec order by cnt,id) <5 then 'false'
    else
    'true'
    end as "show"
    from cte
  

ДЕМОНСТРАЦИЯ