Как сделать агрегирование диапазонов, когда диапазоны перекрываются? - PullRequest
1 голос
/ 04 апреля 2020

Предположим, у меня есть таблица со столбцом цифр c с именем score.

 id  | score 
-----+-------
   1 |   817
   2 |    57
   3 |   571
   4 |   906
   5 |   496
   6 |   129
   7 |    93
 ... |  ...

В стандартном SQL или Postgresql как создать таблицу подсчетов по диапазону с этими диапазонами перекрытие ?

score_range | count 
-------------+-------
 0-20        |     9
 15-50       |    25
 25-*        |   597

Решение case when здесь неприменимо, так как возвращает только первый сегмент, к которому принадлежит счет.

Ответы [ 2 ]

1 голос
/ 04 апреля 2020

Используйте производную таблицу для определения диапазонов. Тогда left join и group by:

select v.range, count(t.score)
from (values  ('0-20', 0, 20),
              ('15-50', 15, 50),
              ('25-*', 25, null)
     ) v(range, lo, hi) left join
     t 
     on t.score >= v.lo and (t.score <= v.hi or v.hi is null)
group by v.range
order by v.lo;
0 голосов
/ 04 апреля 2020

Для этого вы можете использовать Postgres 'типы диапазонов вместе с оператором удержания (@>):

select r.score_range, count(*)
from (values 
    ('0-20', '[0, 20]'::int4range), 
    ('15-50', '[15, 50]'::int4range), 
    ('25-*', '[25,]'::int4range)
) r(score_range, rg)
left join mytable t on r.rg @> t.score
group by r.score_range

'[0, 20]'::int4range представляет диапазон целых чисел для 0 (включительно) до 20 (включительно). '[25,]'::int4range представляет диапазон от 25 (включительно) до бесконечности. Если вам нужны исключительные диапазоны, вы можете использовать круглые скобки (()) вместо квадратных скобок ([]).

...