使用sql query / plpgsql在sql中对给定范围进行顺序分组

时间:2018-05-27 11:33:21

标签: sql postgresql

我需要按顺序对给定组范围的值进行分组

例如:

以下是表格,我需要根据给定的分组 组范围

+----+--------+
| 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 :(得分:1)

您可以分配组,然后这是间隙和岛屿问题:

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 
     )

答案 1 :(得分:0)

您可以使用子选择来构建您的组,然后使用聚合功能和分组

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