通过重复属性的Postgree双组

时间:2015-05-14 00:25:44

标签: ruby-on-rails postgresql group-by postgresql-9.3

我的表有一些列:id,user_id,message_id,message_type;例如:

class A{
  class B{
    def foo = 1
  }
}

class C extends A{
  class B extends super.B{
    override def foo = 2
  }
}

我希望在社交网络中获得分组结果,例如新闻。在列user_id和message_type上,而message_type重复。并且需要LIMIT 20 ORDER BY id DESC。 例如:

  id: 1, user_id: 1, message_id: 4, message_type: 'Warning'
  id: 2, user_id: 1, message_id: 5, message_type: 'Warning'
  id: 3, user_id: 1, message_id: 6, message_type: 'Warning'
  id: 4, user_id: 2, message_id: 4, message_type: 'Error'
  id: 5, user_id: 2, message_id: 1, message_type: 'Exception'
  id: 6, user_id: 1, message_id: 2, message_type: 'Exception'
  id: 7, user_id: 1, message_id: 3, message_type: 'Exception'
  id: 8, user_id: 2, message_id: 4, message_type: 'Exception'

如何以最佳表现做到这一点?

2 个答案:

答案 0 :(得分:1)

我发现只有一种方式:

  1. 使用窗口函数lead()找到更改dict (user, message type)
  2. 的时刻
  3. 使用窗口函数sum()为每个新字典设置序号
  4. 按顺序分组并选择您需要的内容:
  5. 检查:

    create table test (
      id serial primary key,
      user_id integer,
      message_id integer,
      message_type varchar
    );
    
    insert into test (user_id, message_id, message_type) 
    values 
    (1, 4, 'Warning'),
    (1, 5, 'Warning'),
    (1, 6, 'Warning'),
    (2, 4, 'Error'),
    (2, 1, 'Exception'),
    (1, 2, 'Exception'),
    (1, 3, 'Exception'),
    (2, 4, 'Exception')
    ;
    
    select 
        array_agg(grouped.id) as record_ids,
        grouped.user_id,
        array_agg(grouped.message_id) as message_ids,
        grouped.message_type
    from (
        select changed.*, 
            sum(changed.changed) over (order by changed.id desc) as group_n
        from (
            select tt.*,
                case when lag((user_id, message_type)) over (order by tt.id desc) is distinct from (user_id, message_type) then 1 else 0 end as changed
            from test tt
        ) changed
        order by id desc
    ) grouped
    group by grouped.group_n, grouped.user_id, grouped.message_type
    order by grouped.group_n
    ;
    

    结果:

    record_ids | user_id | message_ids | message_type 
    ------------+---------+-------------+--------------
     {8}        |       2 | {4}         | Exception
     {7,6}      |       1 | {3,2}       | Exception
     {5}        |       2 | {1}         | Exception
     {4}        |       2 | {4}         | Error
     {3,2,1}    |       1 | {6,5,4}     | Warning
    (5 rows)
    

答案 1 :(得分:0)

array_agg函数应该可以解决问题:

SELECT   user_id, 
         message_type, 
         ARRAY_AGG (DISTINCT id), 
         ARRAY_AGG (DISTINCT message_id)
FROM     mytable
GROUP BY user_id, message_type