sql - 需要在 SQL 中找到按 ID 分组的前 3 条记录的平均值

标签 sql postgresql greatest-n-per-group average

我有一个包含客户 ID、日期和整数的 postgres 表。我需要找到日期在去年的每个客户 ID 的前 3 条记录的平均值。我可以使用下面的 SQL 使用单个 ID 来完成此操作(id 是客户 ID,周末是日期,maxattached 是整数)。

需要注意的是:最大值是每月,这意味着我们只查看给定月份的最高值来创建数据集,这就是我们从日期中提取月份的原因。

SELECT 
  id,
  round(avg(max),0) 
FROM 
  (
   select 
     id,
     extract(month from weekending) as month,
     extract(year from weekending) as year,
     max(maxattached) as max 
   FROM 
     myTable 
   WHERE
     weekending >= now() - interval '1 year' AND 
     id=110070 group by id,month,year 
   ORDER BY
     max desc limit 3
   ) AS t 
GROUP BY id;

如何扩展此查询以包含所有 ID 以及每个 ID 的单个平均数?

这里是一些示例数据:

ID     | MaxAttached | Weekending
110070 | 5           | 2011-11-10
110070 | 6           | 2011-11-17
110071 | 4           | 2011-11-10
110071 | 7           | 2011-11-17
110070 | 3           | 2011-12-01
110071 | 8           | 2011-12-01
110070 | 5           | 2012-01-01
110071 | 9           | 2012-01-01

因此,对于这个示例表,我希望收到以下结果:

ID     | MaxAttached

110070 | 5           
110071 | 8

这对每个 ID 指定月份的最高值进行平均(110070 为 6,3,5,110071 为 7,8,9)

注意:postgres 版本 8.1.15

最佳答案

首先 - 获取每个客户和月份的max(maxattached):

SELECT id,
       max(maxattached) as max_att         
FROM myTable 
WHERE weekending >= now() - interval '1 year' 
GROUP BY id, date_trunc('month',weekending);

下一步 - 对于每个客户,对他的所有值(value)观进行排名:

SELECT id,
       max_att,
       row_number() OVER (PARTITION BY id ORDER BY max_att DESC) as max_att_rank
FROM <previous select here>;

下一步 - 为每个客户获取前 3 名:

SELECT id,
       max_att
FROM <previous select here>
WHERE max_att_rank <= 3;

下一步 - 获取每个客户的平均值值:

SELECT id,
       avg(max_att) as avg_att
FROM <previous select here>
GROUP BY id;

下一步 - 只需将所有查询放在一起,然后根据您的情况重写/简化它们。

更新:这是一个包含您的测试数据和查询的 SQLFiddle:SQLFiddle .

UPDATE2:这是查询,将在 8.1 上运行:

SELECT customer_id,
       (SELECT round(avg(max_att),0)
        FROM (SELECT max(maxattached) as max_att         
              FROM table1
              WHERE weekending >= now() - interval '2 year' 
                AND id = ct.customer_id
              GROUP BY date_trunc('month',weekending)
              ORDER BY max_att DESC
              LIMIT 3) sub 
        ) as avg_att
FROM customer_table ct;

想法 - 获取初始查询并为每个客户运行它(customer_table - 包含客户所有唯一 id 的表)。

这是包含此查询的 SQLFiddle:SQLFiddle .

仅在版本 8.3 上进行测试(8.1 太旧,无法在 SQLFiddle 上运行)。

关于sql - 需要在 SQL 中找到按 ID 分组的前 3 条记录的平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14296002/

相关文章:

mysql - MySQL 中何时使用单引号、双引号和反引号

c# - SQL 行更新在 C# 中不起作用

java - PostgreSQL- getColumnName 不工作,返回别名

mysql - 检索每个组中的最后一条记录 - MySQL

sql - 处理 if a>b 的最佳方法

sql - 跨实例导入/导出 Sql Server 2005 用户/权限的简便方法?

postgresql - PostgreSQL View 查询的性能

postgresql - 有没有办法在 PostgreSQL 数据库上设置最大行数?

mysql - 根据相关性查找数据,然后从不同域中获取 2 个结果

mysql - 从MySQL数据中获取最后的mod_date