使用某个日期范围内的数据创建多个 SUM 列,其中一列合并了第三个连接 table 中的数据

Create multiple SUM columns with data from a date range, where one column combines data from a joined third table

我正在创建一个查询,该查询按 'entity' 列分组并输出 4 个新列。

关于如何使以下查询成为可能的任何指导?或有关更高效查询的指导?
我正在构建的实际查询在第二个代码块中。

SELECT
    ent.entity,
    SUM(data.amount) curr_month /* when data.ds between 1st of current month AND current date)*/
    SUM(data.amount) prev_month /* when data.ds between 1st of previous month AND current date)*/
    (SUBTRACT prev_month sum from curr_month sum) movement,
    (
      SUM(prev_data.amount) /* when prev_data.ds between 1st day of Previous year AND current date)*/
      + SUM(data.amount) /* when data.ds between 1st day of Current year AND current date)*/
    ) previous_year
FROM entity_table ent
JOIN current_year_table data
    ON data.unit = ent.unit
JOIN previous_year_table prev_data
    ON prev_data.unit = ent.unit
GROUP BY
    entity;

我当前执行的上述查询

这没有 'previous_year_table' 加入,到目前为止似乎可以工作,但感觉很老套。 我也使用 prestodb 语法,例如DATE_TRUNCcurrent_date

SELECT
    ent.entity,
    SUM(
        CASE
            WHEN data.ds BETWEEN CAST(DATE_TRUNC('month', current_date) AS VARCHAR)
                AND CAST(current_date AS VARCHAR) THEN data.amount_usd
            ELSE 0
        END
    ) curr_month,
    SUM(
        CASE
            WHEN data.ds BETWEEN CAST(
                (DATE_TRUNC('month', current_date) - INTERVAL '1' MONTH) AS VARCHAR
            ) AND CAST(current_date AS VARCHAR) THEN data.amount_usd
            ELSE 0
        END
    ) prev_month,
    (
        SUM(
            CASE
                WHEN data.ds BETWEEN CAST(DATE_TRUNC('month', current_date) AS VARCHAR)
                    AND CAST(current_date AS VARCHAR) THEN data.amount_usd
                ELSE 0
            END
        ) - SUM(
            CASE
                WHEN data.ds BETWEEN CAST(
                    (DATE_TRUNC('month', current_date) - INTERVAL '1' MONTH) AS VARCHAR
                ) AND CAST(current_date AS VARCHAR) THEN data.amount_usd
                ELSE 0
            END
        )
    ) movement
FROM entity_table ent
JOIN current_year_table data
    ON data.operating_unit = ent.operating_unit
GROUP BY
    entity;

所需的查询输出

entity current_month previous_month movement(curr - prev) previous_year
entity_1 20 40 -20 70
entity_2 10 50 -40 90

查询输入表

Entity_Table 单位列与####_Year_Table 单位列之间的'many' 关系

Entity_Table

entity unit (join col)
entity_1 1
entity_2 2

当前_Year_Table

unit (join col) amount ds (datestamp string, curr year)
1 20 2022-05-21
1 20 2022-04-19
2 10 2022-05-20
2 40 2022-04-26

上一个_Year_Table

unit (join col) amount ds (datestamp string, prev year)
1 20 2021-08-29
2 30 2021-03-18
2 10 2021-01-21
1 10 2021-02-13

你的 movement 公式很奇怪,原因是这两个:

curr_month /* when data.ds between 1st of current month AND current date)/
prev_month /
when data.ds between 1st of previous month AND current date)*/

movement 将始终只是上个月(一个月的第一天和最后一天之间)的一些负号。

另外,根据数据,似乎 previous_year 您实际上需要当前年份和前几年的总和。

除此之外,您的方法还不错,我建议使用 if 进行小的调整,子选择并使用数据函数以使其更具可读性:

--sample data
WITH entity_table  (entity, operating_unit) AS (
    VALUES  ('entity_1', 1),
    ('entity_2', 2)
),
current_year_table (operating_unit, amount_usd, ds) AS (
    VALUES  
(1, 20, '2022-05-21'),
(1, 20, '2022-04-19'),
(2, 10, '2022-05-20'),
(2, 40, '2022-04-26')
),
previous_year_table (operating_unit, amount_usd, ds) AS (
    VALUES  
(1, 20, '2021-08-29'),
(2, 30, '2021-03-18'),
(2, 10, '2021-01-21'),
(1, 10, '2021-02-13')
)

查询:

-- query
select entity,
    curr_month,
    prev_month,
    curr_month - prev_month as movement,
    total_current_year + previous_year as previous_year
from (
        select ent.entity,
            ent.operating_unit,
            sum(
                if(
                    DATE_TRUNC('month', date(data.ds)) = DATE_TRUNC('month', now()),
                    amount_usd,
                    0
                )
            ) curr_month,
            sum(
                if(
                    // use = instead of >= if you want actual diff between current and previous month
                    DATE_TRUNC('month', date(data.ds)) >= DATE_TRUNC('month', now()) - interval '1' month,
                    amount_usd,
                    0
                )
            ) prev_month,
            sum(amount_usd) total_current_year
        FROM entity_table ent
            JOIN current_year_table data ON data.operating_unit = ent.operating_unit
        GROUP BY entity,
            ent.operating_unit
    ) as current_year_data
    join (
        select operating_unit,
            sum(amount_usd) as previous_year
        from previous_year_table
        group by operating_unit
    ) previous_year_data on current_year_data.operating_unit = previous_year_data.operating_unit

输出:

entity curr_month prev_month movement previous_year
entity_1 20 40 -20 70
entity_2 10 50 -40 90