【问题标题】:SQL Window function to divide a column into 4 groupsSQL Window函数将一列分成4组
【发布时间】:2020-03-13 23:12:25
【问题描述】:

我想以这样一种方式划分行,使每组的收入总和大约相等(在本例中为 50)

在此处查看组:

【问题讨论】:

  • 如果您有 6 行,其中 1 行 150 行,其他 5 行 10 行怎么办?您要求的内容很复杂,您需要准确描述您认为这将如何工作。
  • @GMB 感谢您的回复,在上述情况下,10 行以上的 5 行将属于第 1 组,而 150 行将属于第 4 组。基本上我想将收入分成 25% 相等的收入组.

标签: sql sum amazon-redshift window-functions


【解决方案1】:

这是一种使用窗口函数的方法:

select
    usr,
    revenue, 
    r_revenue running_revenue,
    sum(case 
        when lag_r_revenue is null or r_revenue / divisor <> lag_r_revenue / divisor 
        then 1 else 0 
    end) over(order by revenue, usr) grp
from (
    select t.*, lag(r_revenue) over(order by revenue, usr) lag_r_revenue
    from (
        select 
            t.*, 
            sum(revenue) over(order by revenue, usr) r_revenue, 
            sum(revenue) over() / 4 divisor
        from mytable t
    ) t
) t
order by running_revenue

最内层子查询计算revenue(别名r_revenue)的运行总和;它还通过将总收入除以 4 来计算每组的目标收入。

下一级将之前的运行收入添加到每一行 (lag_r_revenue)。

最后,外部查询执行一个窗口总和,每次运行总和与每组目标数量之间的(整数)比率发生变化时都会增加。

Demo on DB Fiddle:

用户名 |收入 | running_revenue | grp --: | ------: | --------------: | --: 1 | 5 | 5 | 1 2 | 5 | 10 | 1 3 | 10 | 20 | 1 4 | 15 | 35 | 1 5 | 15 | 50 | 2 6 | 20 | 70 | 2 7 | 20 | 90 | 2 8 | 25 | 115 | 3 9 | 30 | 145 | 3 10 | 55 | 200 | 4

【讨论】:

  • 你需要递归来解决我觉得的这类问题,尝试设置 5 个用户,每个用户的值为 5。如果我们要使用预先计算基于表中现有记录的值
【解决方案2】:

要解决这类问题,您需要递归 cte。在这里,我有一个表,5 条记录的值为 5。所以每个 grp 你会期望 1 因为将是 25/4 > 5

create table data_tbl
as 
select * from (values
        (1, 5), 
        (2, 5),
        (3, 5),
        (4, 5),
        (5, 5)
          ) as t(user1, revenue)

 with recursive data
      as (select user1
                 ,revenue
                 ,(sum(revenue) over())/4 as qtr_revenue
                 ,cast(1 as int) as grp
            from data_tbl
           where user1=1 /* start with the first user*/
         union all
          select b.user1
                 ,case when b.revenue+a.revenue<=a.qtr_revenue then
                                  b.revenue+a.revenue
                             else b.revenue
                   end as revenue
                 ,a.qtr_revenue
                 ,case when b.revenue+a.revenue<=a.qtr_revenue then
                                  a.grp
                             else a.grp+1
                   end as grp
            from data a
            join data_tbl b
              on b.user1=a.user1+1
          )
    select *
      from data
    order by user1

查看 db fiddle 链接 https://dbfiddle.uk/?rdbms=postgres_12&fiddle=d8d0d85e4d825af63c09f311302e3510

【讨论】:

    猜你喜欢
    • 2020-12-26
    • 1970-01-01
    • 2011-12-07
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    相关资源
    最近更新 更多