通过不同的时间间隔获取汇总结果

时间:2019-12-27 12:47:40

标签: sql postgresql plpgsql

我有一个postgres DB,其表包含根据ID和时间戳的数据。 该表有几列数据。我想创建一个pgsql函数,该函数可以让我根据时间间隔来收集数据。

表看起来像这样:

   user_id  |     created_at      | value_a | value_b | value_c | value_d | unique_key
------------+---------------------+---------+---------+---------+---------+------------
 1          | 2019-12-16 17:37:07 |    1    |    5    |    0    |    5    |  1
 2          | 2019-12-19 15:37:07 |    4    |    7    |    0    |   42    |  2
 3          | 2019-12-16 15:37:07 |   20    |    1    |   20    |  143    |  3
 2          | 2019-12-18 12:01:32 |    0    |    0    |    5    |  987    |  4
 1          | 2019-12-11 14:12:50 |    6    |    0    |    9    |    0    |  5
 2          | 2019-12-10 15:37:07 |    1    |   72    |  100    |   90    |  6
 1          | 2019-12-20 15:37:07 |    5    |    3    |   56    | 1546    |  7
 3          | 2019-12-20 15:37:07 |   30    |    4    |  789    |    3    |  8
 4          | 2019-12-01 15:37:07 |   35    |   90    |    0    |    5    |  9
(9 rows)

我想以可以获取时间范围(之前和之后)和时间间隔的方式创建函数,以便随后根据时间间隔(例如每天)将数据分组(按{{1}分组) }。 我设法创建了一个带有user_id的函数,该函数返回汇总的结果,但是它忽略了某些数据。 聚合使用不同的公式来获取数据。

我找到的大多数答案设法选择了一个只有一个值而不是多个I.E的分组和。它返回以下内容:

generate_series

但是就我而言,我想以不同的方式来处理数据,例如:

user_id | date | value_a + value_b + value_c + value_c

等(当然,我将处理零和除数)。

因此,我尝试创建的功能类似于以下内容:

user_id | date | a + b | (a*b)/c | count(a)

遗憾的是,这种查询类型不会根据所有可用日期返回表中的所有可用数据。

有什么办法可以针对我需要的情况针对我对generate_series的正确使用提出建议吗?

P.S。 我知道总和的功能将不起作用,仅用于示例:)

非常感谢!

1 个答案:

答案 0 :(得分:1)

欢迎堆栈溢出。

您的函数有一些语法错误。这就是您要寻找的东西:

CREATE OR REPLACE FUNCTION branch_performance_measurements_daily(
  after DATE, before DATE)
RETURNS TABLE (
  date_of_sum DATE, func_a BIGINT,func_b BIGINT, func_c BIGINT) AS $$
BEGIN
RETURN QUERY
  WITH days_series AS (
    SELECT generate_series(after, before, '1 day') AS d)
  SELECT 
    DATE(ds.d) AS date_of_sum, 
    sum(value_a + value_b),
    COALESCE(sum((value_a*value_b)/NULLIF(value_c,0)),0),
    count(value_a) FROM t
  JOIN days_series ds ON ds.d = DATE(t.created_at)
  GROUP BY ds.d, t.user_id
  ORDER BY ds.d;
END;
$$ LANGUAGE plpgsql;

样本数据

CREATE TEMPORARY TABLE t 
(user_id INT, created_at date, 
 value_a int,value_b int,value_c int,value_d int, unique_key int);

INSERT INTO t VALUES
 (1,' 2019-12-16 17:37:07',1,5,0,5,1),
 (2,' 2019-12-19 15:37:07',4,7,0, 42,2),
 (3,' 2019-12-16 15:37:07',20,1,20,143,3),
 (2,' 2019-12-18 12:01:32',0,0,5,987,4),
 (1,' 2019-12-11 14:12:50',6,0,9,0,5),
 (2,' 2019-12-10 15:37:07',1,72,100, 90,6),
 (1,' 2019-12-20 15:37:07',5,3,56,1546,7),
 (3,' 2019-12-20 15:37:07',30,4,789,3,8),
 (4,' 2019-12-01 15:37:07',35, 90,0,5,9);

测试功能

SELECT * FROM branch_performance_measurements_daily('2019-12-01', '2019-12-20');
 date_of_sum | func_a | func_b | func_c 
-------------+--------+--------+--------
 2019-12-01  |    125 |      0 |      1
 2019-12-10  |     73 |      0 |      1
 2019-12-11  |      6 |      0 |      1
 2019-12-16  |      6 |      0 |      1
 2019-12-16  |     21 |      1 |      1
 2019-12-18  |      0 |      0 |      1
 2019-12-19  |     11 |      0 |      1
 2019-12-20  |      8 |      0 |      1
 2019-12-20  |     34 |      0 |      1
(9 rows)

如果您只想按生成的日期进行分组(如查询所建议,不与user_id一起分组),只需从user_id子句中删除GROUP BY,您将得到这样的东西:

 date_of_sum | func_a | func_b | func_c 
-------------+--------+--------+--------
 2019-12-01  |    125 |      0 |      1
 2019-12-10  |     73 |      0 |      1
 2019-12-11  |      6 |      0 |      1
 2019-12-16  |     27 |      1 |      2
 2019-12-18  |      0 |      0 |      1
 2019-12-19  |     11 |      0 |      1
 2019-12-20  |     42 |      0 |      2