限制平均使用的行数

时间:2013-04-16 12:06:57

标签: sql postgresql limit

我有一个查询(postgresql),我想限制用于计算平均值的行

SELECT username,avg(income),count(*) FROM
       Events 
WHERE to_timestamp(eventtimestamp)  >=  '2008-02-23' AND 
      to_timestamp(eventtimestamp) <=   '2009-01-03' and username='Joe'
GROUP BY userid 

Joe有40个条目,但我想限制用于计算其收入平均值的行数。我知道我可以在查询结尾处添加的限制功能,但这会限制整个查询的输出,而不是<查询头部中的strong> average 命令。有什么提示我怎么能告诉avg只使用前n行?

e.g。 无法正常工作

SELECT username,avg(income) limit 5,count(*) FROM
       Events 
WHERE to_timestamp(eventtimestamp)  >=  '2008-02-23' AND 
      to_timestamp(eventtimestamp) <=   '2009-01-03' and username='Joe'
GROUP BY userid 

仅在前5行中平均。

谢谢!

5 个答案:

答案 0 :(得分:3)

我正在添加答案有两个原因。首先,大多数其他答案会影响count(*)以及avg(),这不是问题的一部分。其次,您可能希望为多个用户执行此操作。

所以,您可以尝试以下方法:

SELECT username, avg(case when seqnum <= 40 then income end), count(*)
FROM (select e.*, ROW_NUMBER() over (partition by username order by eventtimestamp desc) as seqnum
      from Events e
      WHERE to_timestamp(eventtimestamp)  >=  '2008-02-23' AND 
            to_timestamp(eventtimestamp) <=   '2009-01-03'
     ) e
GROUP BY username

答案 1 :(得分:2)

您可以采用内部查询的平均值:

SELECT username,avg(income),count(*)
FROM (
  SELECT username, income
  FROM Events 
  WHERE to_timestamp(eventtimestamp) BETWEEN '2008-02-23' AND '2009-01-03'
  and username='Joe'
  LIMIT 5) x
GROUP BY userid;

另请注意使用BETWEEN

进行简化

答案 2 :(得分:1)

您可以在子选择中使用限制;

SELECT username,avg(income),count(*) FROM
  (SELECT * FROM Events 
   WHERE to_timestamp(eventtimestamp)  >=  '2008-02-23' AND 
      to_timestamp(eventtimestamp) <=   '2009-01-03' and username='Joe'
   order by to_timestamp(eventtimestamp) desc
   LIMIT 10) sub
GROUP BY userid;

答案 3 :(得分:1)

如果你偶然喜欢(或者不关心)5行的平均值,那么你可以使用窗函数来避免使用子选项:

select
    username,
    avg(income) over(rows 4 preceding),
    count(*)
from events 
where to_timestamp(eventtimestamp)  >=  '2008-02-23' and 
      to_timestamp(eventtimestamp) <=   '2009-01-03' and username='joe'
group by userid

如果我理解你的评论,你确实可以使用count作为窗口函数:

    count(*) over(rows 4 preceding)

或者如果不想计算空值:

    count(income) over(rows 4 preceding)

答案 4 :(得分:0)

已发布好的答案。我建议使用Unix纪元进行比较和排序如下:

SELECT userid, username, avg(income), count(*)
FROM (
  SELECT userid, username, income
  FROM Events 
  WHERE eventtimestamp BETWEEN date_part('epoch', '2008-02-23'::date) 
      AND date_part('epoch', '2009-01-03'::date)
    AND username='Joe'
  ORDER BY eventtimestamp DESC LIMIT 10) AS q
GROUP BY userid, username;

通过这样做,我没有为每一行调用转换函数。另一种方法可能是在to_timestamp(eventtimestamp)上创建一个功能索引,但我认为我这样做的方式更有效。

请注意,我已经包含了userid和username - 原始示例会抛出错误,因为username不在'GROUP BY'子句中。

除此之外,如果您想从随机样本而不是最后的 n 条目进行计算,您可以将排序更改为ORDER BY random()