Последовательная группировка в sql для заданных диапазонов с использованием sql query / plpgsql - PullRequest
0 голосов
/ 27 мая 2018

Мне нужно последовательно сгруппировать значения для заданных диапазонов групп

Например:

Ниже приведена таблица, в которой мне нужно группировать на основе заданных диапазонов групп

+----+--------+
| id | values |
+----+--------+
|  1 |       8|
|  2 |       9|
|  3 |      10|
|  4 |      11|
|  5 |      12|
|  6 |      16|
|  7 |      17|
|  8 |       1|
|  9 |       7|
| 10 |       9|
| 11 |      18|
| 12 |      19|
+----+--------+

Диапазоны групп:

   Group-1: [0-5]

   Group-2: [6-10]

   Group-3: [11-15]

   Group-4: [16-20]

Ожидается следующий вывод после группировки (только с помощью запроса):

+---+--------------+-------------+-----------+---------------+
|id | values_group | start_value | end_value | average_value |
+---+--------------+-------------+-----------+---------------+
| 1 |       Group-2|            8|         10|            9  |
| 2 |       Group-3|           11|         12|         11.5  |
| 3 |       Group-4|           16|         17|         16.5  |
| 4 |       Group-1|            1|          1|            1  |         
| 5 |       Group-2|            7|          9|            8  |
| 6 |       Group-4|           18|         19|         18.5  |
+---+--------------+-------------+-----------+---------------+

Как это сделать с помощью SQL-запроса / plpgsql без каких-либозацикливание

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

Вы можете назначить группы, и тогда это проблема пробелов и островов:

with t as (
      select t.*,
              (case when value >= 0 and value <= 5 then 'Group 1'
                    when value >= 6 and value <= 10 then 'Group 2'
                    when value >= 11 and value <= 15 then 'Group 3'
                    when value >= 16 and value <= 20 then 'Group 4'
               end) as grp
      from t 
     )
select row_number() over (order by min(id)) as new_id,
       grp, min(value), max(value), avg(value)
from (select t.*,
             row_number() over (order by id) as seqnum,
             row_number() over (partition by grp order by id) as seqnum_g
      from t
     ) t
group by (seqnum - seqnum_g), grp;

Я почти уверен, что вы можете упростить логику case до:

with t as (
      select t.*,
              (case when value <= 5 then 'Group 1'
                    when value <= 10 then 'Group 2'
                    when value <= 15 then 'Group 3'
                    else 'Group 4'
               end) as grp
      from my_table 
     )
0 голосов
/ 27 мая 2018

Вы можете использовать подвыбор для построения вашей группы, а затем использовать функцию агрегирования и группировать по

select my_group, mix(values), max(values), avg(values)
from (

    select case when value >= 0 and <= 5 then 'Group 1'
                when value >= 6 and <= 10 then 'Group 2'
                when value >= 11 and <= 15 then 'Group 3'
                when value >= 16 and <= 20 then 'Group 4' end my_group,
                values 
    from my_table 


    ) t 
    group by my_group 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...