如何获得每组中所有列都加上每组的组计数列的最新记录?

时间:2019-07-17 12:07:00

标签: postgresql

查看表格:

CREATE TABLE event(
    event_id UUID PRIMARY KEY,
    user_id UUID NOT NULL,
    trigger_id UUID NOT NULL,
    name VARCHAR (255) NOT NULL,
    type VARCHAR (50) NOT NULL,
    trigger_name VARCHAR (255) NOT NULL,
    status smallint,
    date_created TIMESTAMP NOT NULL DEFAULT NOW(),
);

我想

1)首先按“类型” ASC排序,然后按“ date_created” DESC排序

这部分很容易像这样

SELECT *
FROM event
WHERE user_id = 'fd80059a-3a16-40fe-9f6b-ad2812875d92'
ORDER BY type ASC, date_created DESC

2)按“ trigger_id”,“ type”和“ name”分组,并为每个分组计数。是的,如果“ trigger_id”,“ type”和“ name”相同,我想组成一个小组,并显示最近的一个小组,并对该小组中的所有事件进行计数(基本上是事件发生了多少次,因为如果这三个相同,则可以认为该事件是相关的。

这是具有挑战性的部分。理想的情况是这样的:

SELECT * --, count(since the count/grouping is based on 3 columns, how??)
FROM event
WHERE account_id = 'fd80059a-3a16-40fe-9f6b-ad2812875d92'
ORDER BY type ASC, date_created DESC
GROUP BY trigger_id, type, name

将只给我每组中的第一条记录(因为它们已经按日期排序了),但是所有的列(而不只是GROUP BY子句中的列)加上​​最后的组计数列。

我现在使用选项1解决此问题,然后在我的节点API中使用以下javascript代码,但是如果您了解该代码段,那么它的功能正是我在postgres中需要做的:

[...arrayOfEventsFromDB.reduce((r, o) => {
    const key = `${o.trigger_id}-${o.type}-${o.name}`;

    const item = r.get(key) || Object.assign({}, o, {
      count: 0,
    });

    item.count++;

    return r.set(key, item);
  }, new Map).values()];

但是理想情况下,如果postgres非常适合这种聚合,我想在SQL查询中做到这一点。

编辑

由于我无法在答案中粘贴代码。

这里要求通过结合以下两个答案,来不断完善表创建,数据和SELECT查询。所有这些子选择似乎效率不高,但可以使用。

https://www.db-fiddle.com/f/mNNzwiDbx2iUdgd2vFTRuJ/0

SELECT *
FROM (
  SELECT DISTINCT ON (trigger_id, type, name)
      *
      FROM (
          SELECT *,
          row_number () over(PARTITION BY trigger_id, type, name order by date_created DESC )
          FROM (
              SELECT
                  *,
                  COUNT(*) OVER (PARTITION BY trigger_id, type, name)
              FROM event
              WHERE user_id = 1
              ORDER BY type ASC, date_created DESC
          ) s
      ) t
  ) u
  ORDER BY type ASC, date_created DESC

2 个答案:

答案 0 :(得分:1)

Window functions来拯救您(编辑:还有DISTINCT ON):

SELECT DISTINCT ON (type, date_created)
    *
FROM (
    SELECT
        *,
        COUNT(*) OVER (PARTITION BY trigger_id, type, name)
    FROM event
    WHERE account_id = 'fd80059a-3a16-40fe-9f6b-ad2812875d92'
) s
ORDER BY type ASC, date_created DESC  

编辑:聊天后,此解决方案最合适:

SELECT *
FROM (
    SELECT DISTINCT ON (trigger_id, type, name)
        *
    FROM (
         SELECT *
         FROM (
             SELECT
                 *,
                 COUNT(*) OVER (PARTITION BY trigger_id, type, name)
             FROM event
             WHERE user_id = 1
         ) s
    ) t
    ORDER BY trigger_id, type, name, date_created DESC
) u
ORDER BY type ASC, date_created DESC

答案 1 :(得分:0)

您可以检查以下查询

SELECT * 
FROM (
    SELECT
        a.*,
        COUNT(*) OVER (PARTITION BY trigger_id, type, name) cnt , row_number () over(PARTITION BY trigger_id, type, name order by date_created DESC ) rn
    FROM event a
    WHERE account_id = 'fd80059a-3a16-40fe-9f6b-ad2812875d92'
) s
where rn < = 4 
ORDER BY type ASC, date_created DESC