PostgreSQL - 按结果将最新记录加入到组中

时间:2017-12-11 10:35:17

标签: sql postgresql

以下按预期工作,但在优化方面,你们有时可以做出魔术。这是正确的还是可以更好/更快的方式完成?

WITH last_events AS (
    SELECT DISTINCT ON (type, adid)
        type,
        adid,
        value,
        created_at
    FROM public.adid
    ORDER BY type, adid, created_at DESC
)
SELECT
    adid.type,
    adid.adid,
    count(*) as count,
    sum(adid.value) as summary,
    le.created_at
FROM public.adid
JOIN last_events le ON le.type = adid.type AND le.adid = adid.adid
GROUP BY adid.type, adid.adid, le.created_at
ORDER BY summary DESC, le.created_at DESC;

1 个答案:

答案 0 :(得分:2)

我相信解决方案的某些部分是不必要的。 CTE每created_at组返回最多(type,adid)个。主查询计算每(type,adid)组的行数和value(type,adid)组的总和。因此,它可以这样写成

SELECT
    adid.type,
    adid.adid,
    count(*) as count,
    sum(adid.value) as summary,
    max(adid.created_at) max_created_at
FROM public.adid
GROUP BY adid.type, adid.adid
ORDER BY summary DESC, max_created_at DESC;

如果您对与created_at行最高的行对应的其他列感兴趣,那么您可以使用经典的每组最大方法之一。我更喜欢的是使用GROUP BY来找到最大的价值(非常类似于你的方法):

SELECT
    adid.type,
    adid.adid,
    t.count,
    t.summary,
    t.max_created_at,
    adid.value
FROM public.adid
JOIN (
  SELECT
    adid.type,
    adid.adid,
    count(*) as count,
    sum(adid.value) as summary,
    max(adid.created_at) max_created_at
  FROM public.adid
  GROUP BY adid.type, adid.adid
) t ON t.type = adid.type and 
       t.adid = adid.adid and 
       t.max_created_at = adid.created_at
ORDER BY t.summary DESC, t.max_created_at DESC;

我认为这样更好,因为我的解决方案只有一个聚合。您的解决方案使用DISTINCT ON(隐藏聚合)和外部联接中的另一个GROUP BY

找到每组最大的另一个选项是使用窗口函数,但是,我认为聚合是一个更好的解决方案,因为您需要更多的聚合值。此外,GROUP BY似乎在certain cases中比窗口函数具有更好的性能。