Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 通过不同的时间间隔获得聚合结果_Sql_Postgresql_Plpgsql - Fatal编程技术网

Sql 通过不同的时间间隔获得聚合结果

Sql 通过不同的时间间隔获得聚合结果,sql,postgresql,plpgsql,Sql,Postgresql,Plpgsql,我有一个postgres DB,其中有一个表,根据id和时间戳包含数据。 该表有多个包含数据的列。我想创建一个pgsql函数,它允许我根据时间间隔获得数据的聚合 该表如下所示: user_id | created_at | value_a | value_b | value_c | value_d | unique_key ------------+---------------------+---------+---------+---------+---------

我有一个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)
 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
我想创建一个函数,这样我可以得到一个时间范围(之前和之后)和一个时间间隔,这样它就可以根据时间间隔(例如每天)对数据进行分组,分组依据
user\u id
。 我已经成功地创建了一个带有
generate_series
的函数,该函数返回聚合结果,但它忽略了一些数据。 聚合使用不同的公式来获取数据

我发现的大多数答案都选择了一个只有一个值的分组和,而不是几个值的分组和,也就是说,它返回的内容大致如下:

user_id | date | value_a + value_b + value_c + value_c

CREATE OR REPLACE FUNCTION branch_performance_measurements_daily(
    IN after DATE,
    IN before DATE,
    )
RETURNS TABLE (
      date_of_sum DATE,
      func_a INT,
      func_b INT,
      func_c INT
)
AS $$
BEGIN
    RETURN QUERY
    WITH days_series AS (
        SELECT d::date day FROM generate_series(after, before, '1 day') day)
    SELECT days_series.day AS date_of_sum, 
            sum(a + b),
            sum((a*b)/c),
            count(a)

            FROM table b
            WHERE DATE(b.created_at) = DATE(days_series.day)
            GROUP BY days_series.day, b.user_id;
END;
$$ LANGUAGE plpgsql;
但在我的情况下,我希望以不同的方式操纵数据,例如:

user_id | date | a + b | (a*b)/c | count(a)
等等(当然我会处理除以零之类的问题)

因此,我尝试创建的函数大致如下:

user_id | date | value_a + value_b + value_c + value_c

CREATE OR REPLACE FUNCTION branch_performance_measurements_daily(
    IN after DATE,
    IN before DATE,
    )
RETURNS TABLE (
      date_of_sum DATE,
      func_a INT,
      func_b INT,
      func_c INT
)
AS $$
BEGIN
    RETURN QUERY
    WITH days_series AS (
        SELECT d::date day FROM generate_series(after, before, '1 day') day)
    SELECT days_series.day AS date_of_sum, 
            sum(a + b),
            sum((a*b)/c),
            count(a)

            FROM table b
            WHERE DATE(b.created_at) = DATE(days_series.day)
            GROUP BY days_series.day, b.user_id;
END;
$$ LANGUAGE plpgsql;
遗憾的是,这种类型的查询不会根据所有可用日期返回表中的所有可用数据

是否有任何方法可以告诉我如何正确使用generate_系列以满足我的需要

附言。 我知道和的函数不起作用,只是举个例子:)


非常感谢

欢迎使用堆栈溢出

您的函数有一些语法错误。这是您可能正在寻找的:

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)
如果您只想按生成的日期分组(而不是像您的查询建议的那样与
用户id
一起),只需从
group by
子句中删除
用户id
,您将得到如下结果:

   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)
 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

我会求助于java(螺丝锤)之类的编程语言。但我理解的只是SQL中的驻留。您是否必须在之后和之前的日期之间的每个日期都有一行(即使没有数据)?此外,如果您的选择中没有包含按用户id进行分组,那么它似乎毫无意义。这里有一个基本的查询示例,使用select中的user_id:@JoopEggen,我也希望如此,但是我需要在软件级别之前进行这种类型的查询:)@Matt,当然我有一个select:)在将函数传输到这里时,我意外地忽略了它,非常感谢!在回顾了你的答案之后,我似乎只遗漏了我最初未经过滤的问题中很小的一点,谢谢!