return 过去 12 个月每个月在 postgres 中发生的所有记录的总和

how return a sum of all the records happened in every month for the last 12 months in postgres

table 看起来像这样

所以我得到了一个看起来像这样的查询

with date_ranges (range_name, range_dates) as
              ( values ('week_0', tstzrange ((now()::date-interval '6 days'),  now(), '[]'))
                      , ('week_1', tstzrange ((now()::date-interval '13 days'), (now()::date-interval '6 days')))
                      , ('week_2', tstzrange ((now()::date-interval '20 days'), (now()::date-interval '13 days')))
                      , ('week_3', tstzrange ((now()::date-interval '27 days'), (now()::date-interval '20 days')))
              )
                select range_name, range_dates, COALESCE(SUM("transactionTotal"), 0) total_amount 
        from date_ranges dr
        LEFT JOIN "MoneyTransactions" mt on (mt."entryType" = 'sold' AND mt."createdAt" <@ range_dates)
        group by range_name, range_dates
        order by range_name;

它 return 是过去四个星期每周的总和。现在我正在尝试 return 同样的事情,但不是几周,而是过去 12 个月的总和。

我能够获得上个月的所需日期,例如

SELECT
  to_char(now() - series.n * '1 month'::interval, 'month') AS "month",
  tstzrange(
    date_trunc('month', now()) - series.n * '1 month'::interval,
    date_trunc('month', now()) - (series.n - 1) * '1 month'::interval,
    '[]'
  ) AS range_dates
FROM (
  SELECT generate_series(0, 11) AS n
) AS series

我试过了,显然它不起作用

with date_ranges (range_name, range_dates) as
              ( values (
                to_char(now() - series.n * '1 month'::interval, 'month') as "month",
                tstzrange(
                  date_trunc('month', now()) - series.n * '1 month'::interval,
                  date_trunc('month', now()) - (series.n - 1) * '1 month'::interval,
                  '[]'
              ))
              )
            select range_name, range_dates(0, 11), COALESCE(SUM("transactionTotal"), 0) total_amount 
        from date_ranges dr
        LEFT JOIN "MoneyTransactions" mt on (mt."entryType" = 'sold' AND mt."createdAt" <@ range_dates)
        group by range_name, range_dates
        order by range_name;

但是我对 SQL 的有限了解使我无法将所有这些放在一个查询中以获得所需的输出,看起来像这样

[
        {
            "range_name": "september",
            "range_dates": [
                {
                    "value": "2020-09-01T00:00:00.000Z",
                    "inclusive": true
                },
                {
                    "value": "2020-10-01T00:00:00.000Z",
                    "inclusive": false
                }
            ],
            "total_amount": "253050"
        },
        {
            "range_name": "august",
            "range_dates": [
                {
                    "value": "2020-08-01T00:00:00.000Z",
                    "inclusive": true
                },
                {
                    "value": "2020-09-01T00:00:00.000Z",
                    "inclusive": false
                }
            ],
            "total_amount": "55200"
        },
        ...
]

有好心人帮忙吗

这是获得 12 个月范围的更简洁的方法。根据日期在 money_transactions 中的样子,您可以轻松地使用它们与 create_date 列进行比较。

to_char returns 是不同格式的 varchar,在我的示例中,我使用 MM/YYYY,它将 return 10/2019 用于 2019 年 10 月。您必须确保生成的系列日期和 MoneyTransactionscreatedAt 日期格式匹配。不过,您可以随意调整它。

with date_range as 
(
   select
      to_char(months, 'MM/YYYY') as "month" -- returns month/year 10/19
   from
      generate_series( date_trunc('month', current_date - interval '11 months'), date_trunc('month', current_date), '1 month':: interval) as months 
)
select
   dr."month",
   COALESCE(SUM("transactionTotal"), 0) total_amount 
from
   date_range dr 
   left join
      "MoneyTransactions" mt 
      on mt."entryType" = 'sold' 
      and to_char(mt."createdAt", 'MM/YYYY') = dr."month" 
group by
   dr."month";

另外,SQL 命名约定建议在您的标识符(表、列等)中使用 snake_case 和所有小写字母,因此 money_transactions 而不是 MoneyTransactions.