简化 PostgreSQL 中的计算总和(值/row_number),无需显式行号分配

Simplification of the calculation sum(value / row_number) in PostgreSQL without explicit row number assignment

提问人:puchal 提问时间:11/14/2023 更新时间:11/14/2023 访问量:22

问:

我正在使用 PostgreSQL 数据库,我正在寻找一种更有效的计算方式:.sum(value/row_number)

我目前的方法涉及在单独的步骤中分配行号,然后执行求和,但这种方法需要对数据进行两次分组,我想避免这种情况。

-- CREATE TEMP TABLE
CREATE TEMP TABLE test_data (
  value INT,
  group_id INT,
  created_at TIMESTAMP
);

-- PREPARE DUMMY DATA
INSERT INTO test_data VALUES 
  (20, 1, '2023-12-01'),
  (60, 1, '2023-12-02'),
  (5, 2, '2023-12-04'),
  (2, 2, '2023-12-05'),
  (9, 2, '2023-12-08'),
  (100, 3, '2023-12-04'),
  (50, 4, '2023-12-04'),
  (50, 4, '2023-12-07');

-- SELECT QUERY
WITH numbered_data AS (
    SELECT
        value,
        group_id,
        created_at,
        ROW_NUMBER() OVER (PARTITION BY group_id ORDER BY created_at) AS row_n
    FROM
        test_data
)
SELECT
    group_id,
    sum(value / row_n) AS my_result
FROM
    numbered_data
GROUP BY
    group_id;

我想知道是否有可能在更简单的步骤中执行此查询。

不幸的是,聚合函数调用不能包含窗口函数调用,因此这不起作用:

-- NOT WORKING
SELECT
    group_id,
    sum(value / ROW_NUMBER() OVER (ORDER BY created_at) )
FROM
    test_data
GROUP BY group_id
PostgreSQL 和聚合

评论


答:

0赞 Maimoona Abid 11/14/2023 #1

您可以使用 window 函数将查询包装在子查询中。以这种方式,外部查询执行由 group_id 聚合的最终求和,而子查询计算相关窗口中的值 / ROW_NUMBER()。

请尝试此更新版本:

SELECT
    group_id,
    SUM(my_result) AS final_result
FROM (

    SELECT
        group_id,
        value / ROW_NUMBER() OVER (PARTITION BY group_id ORDER BY created_at) AS my_result
    FROM
        test_data
) AS subquery
GROUP BY
    group_id;

希望对:)有所帮助

评论

0赞 puchal 11/14/2023
我已经检查过了,它(几乎)不会改变计划或性能。EXPLAIN ANALYZE