当前位置: 首页 > 面试题库 >

PostgreSQL:“按分钟”运行查询的行数

何建中
2023-03-14
问题内容

我需要查询每一分钟到该分钟为止的总行数。

到目前为止,我能取得的最好成绩并不能解决问题。它返回每分钟的计数,而不是每分钟的总计数:

SELECT COUNT(id) AS count
     , EXTRACT(hour from "when") AS hour
     , EXTRACT(minute from "when") AS minute
  FROM mytable
 GROUP BY hour, minute

问题答案:

仅返回活动的分钟数

最短的

SELECT DISTINCT
       date_trunc('minute', "when") AS minute
     , count(*) OVER (ORDER BY date_trunc('minute', "when")) AS running_ct
FROM   mytable
ORDER  BY 1;
  • 使用date_trunc(),它恰好返回您需要的内容。

  • 不要包含id在查询中,因为您希望记录GROUP BY切片。

  • count()通常用作简单的聚合函数。附加OVER子句使其成为窗口函数。PARTITION BY在窗口定义中忽略-您希望 对所有 行进行 运行计数 。默认情况下,按定义从当前行的第一行到最后一行ORDER BY。我引用该手册:

默认的取景选项为RANGE UNBOUNDED PRECEDING,与相同RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW。使用ORDER BY,这会将帧设置为从分区开始到当前行的最后一个ORDER BY对等方的所有行。

而这恰好 正是 您所需要的。

  • 使用count(*)而不是count(id)。它更适合您的问题(“行数”)。它通常是稍 count(id)。而且,尽管我们可以假设idNOT NULL,但尚未在问题中指定它,因此严格来说count(id)错误的 ,因为NULL值不计入count(id)

  • 您不能GROUP BY在相同的查询级别上记录切片。集合函数 窗口函数 之前 应用,这样窗口函数count(*)每分钟只能看到1行。
    但是,您可以使用,SELECT DISTINCT因为它DISTINCT 窗口功能 之后 应用的。

  • ORDER BY 1只是ORDER BY date_trunc('minute', "when")这里的简写。
    1是对SELECT列表中第一个表达式的位置参考。

  • 使用to_char(),如果你需要格式化的结果。喜欢:

    SELECT DISTINCT
    to_char(date_trunc(‘minute’, “when”), ‘DD.MM.YYYY HH24:MI’) AS minute
    , count(*) OVER (ORDER BY date_trunc(‘minute’, “when”)) AS running_ct
    FROM mytable
    ORDER BY date_trunc(‘minute’, “when”);

最快的

SELECT minute, sum(minute_ct) OVER (ORDER BY minute) AS running_ct
FROM  (
   SELECT date_trunc('minute', "when") AS minute
        , count(*) AS minute_ct
   FROM   tbl
   GROUP  BY 1
   ) sub
ORDER  BY 1;

类似于上面的内容,但是:

  • 我使用子查询来汇总和计算每分钟的行数。这样,我们每分钟就能获得1行,而不会DISTINCT在外部SELECT

  • sum()现在的窗口集合函数从子查询加起来计数。

我发现这样做的速度大大提高,每分钟有很多行。

包括没有活动的分钟

最短的

@GabiMe在评论中询问如何在时间范围内的 每个
minute时间获取eone行,包括没有事件发生的行(基表中没有行):

SELECT DISTINCT
       minute, count(c.minute) OVER (ORDER BY minute) AS running_ct
FROM  (
   SELECT generate_series(date_trunc('minute', min("when"))
                        ,                      max("when")
                        , interval '1 min')
   FROM   tbl
   ) m(minute)
LEFT   JOIN (SELECT date_trunc('minute', "when") FROM tbl) c(minute) USING (minute)
ORDER  BY 1;
  • 在第一个事件与最后一个事件之间的时间范围内,每分钟产生一行generate_series()-使用-这里直接基于子查询的汇总值。

  • LEFT JOIN所有时间戳都将被截断至分钟并计数。NULL值(不存在行)不会添加到运行计数中。

最快的

使用CTE:

WITH cte AS (
   SELECT date_trunc('minute', "when") AS minute, count(*) AS minute_ct
   FROM   tbl
   GROUP  BY 1
   ) 
SELECT m.minute
     , COALESCE(sum(cte.minute_ct) OVER (ORDER BY m.minute), 0) AS running_ct
FROM  (
   SELECT generate_series(min(minute), max(minute), interval '1 min')
   FROM   cte
   ) m(minute)
LEFT   JOIN cte USING (minute)
ORDER  BY 1;
  • 再次,在第一步中汇总并计算每分钟的行数,而忽略了稍后的需求DISTINCT

  • 不同于count()sum()可以退货NULL。默认为0with COALESCE

在使用Postgres 9.1-9.4测试的几个变体中 "when"该版本具有很多行和一个带有子查询的 索引 是最快的:

SELECT m.minute
     , COALESCE(sum(c.minute_ct) OVER (ORDER BY m.minute), 0) AS running_ct
FROM  (
   SELECT generate_series(date_trunc('minute', min("when"))
                        ,                      max("when")
                        , interval '1 min')
   FROM   tbl
   ) m(minute)
LEFT   JOIN (
   SELECT date_trunc('minute', "when") AS minute
        , count(*) AS minute_ct
   FROM   tbl
   GROUP  BY 1
   ) c USING (minute)
ORDER  BY 1;


 类似资料:
  • 我在表中插入了一个数据......我现在想看到整个表的行,列和数据。如何通过命令显示?

  • 问题内容: 我有要求在5分钟内运行一会儿循环。我寻找了计时器api,但找不到这样做。任何人都可以为此提供代码摘要。 谢谢 问题答案: 最简单的方法是只检查每次迭代已花费了多少时间。例: 这将运行循环,直到超过5分钟为止。 笔记: 当前循环迭代将始终完成,因此在实践中它将始终运行5分钟以上。 对于此应用程序而言,它比之更合适,因为如果调整了计算机的系统时钟,后者将发生变化,从而使计算工作中断。 感谢

  • 问题内容: 我在Postgres服务器上有以下数据库表: 我想创建一个查询,给出了的按月份和年份如下列并对结果进行分组: 有没有简单的方法可以做到这一点? 问题答案: 应Radu的要求,我将解释该查询: :将“日期”属性转换为月的简短形式的定义格式。 :Postgresql的“提取”功能用于从“日期”属性中提取YYYY年。 :SUM()函数将所有“ Sales”值相加,并提供区分大小写的别名,并使

  • 问题内容: 我有一个监视系统,它每n秒收集一次数据(n大约为10,但有所不同)。我想每隔15分钟汇总一次收集的数据。有没有一种方法可以将时间戳记值合并为15分钟的块,以便分组工作? 问题答案:

  • 比方说,我有一个购物车的食品杂货,每个项目都有一个唯一的ID。当有人点击“购买”时,会发送一个数组,其中包含购物车中每件商品的对象。购物车各不相同,所以有时可能是2个项目,有时是6个项目,等等。 例子: 我需要我的SQL表“可用的杂货”来根据购买的商品进行更新。 对于一个杂货项目,我会使用以下内容: 既然我现在有多件商品,我如何让查询为购买的每件商品运行?或者作为一个大规模的查询,根据购买的商品数

  • 问题内容: 因此,我想尝试一下Timer和TimerTask类。 30秒过后,我能够执行一行代码。我现在一直想做的是让这行代码执行5分钟。 这是我最初尝试的 我在for循环中使用了数字10,以查看timer.schedule在循环的下一次迭代期间是否还要再等待30秒。 知道我应该怎么做吗?我尝试将schedule方法与传入参数period一起使用,但这只是使其重新执行而从未停止过。 问题答案: 您