Postgres как я могу получить сумму за предыдущий месяц из группы реляционных таблиц по?

#postgresql

Вопрос:

У меня есть два стола

 coins       summary_coins 
--------    -------------
id | name    id| date                |  get_count | coin_id
===|====    ==============================================
 1 |lira     1 | 2020-02-16 16:55:50 |  20        | 1
 2 |A        1 | 2020-03-16 16:55:50 |  12        | 1
 3 |B        1 | 2020-03-16 16:55:50 |  20        | 1
 

Мой ожидаемый результат

 name get_count   previous_month_count  
Lira 32          20
 

По приведенному ниже запросу я могу получить итоговую сумму за текущий месяц

 SELECT Coins.id AS "Coins__id", 
Coins.name AS "Coins__name",  
(SUM(SummaryCoins.get_count)) AS "get_count", 
(SUM(SummaryCoins.get_count)) AS "previous_month_count" 
FROM coins Coins 
INNER JOIN summary_coins SummaryCoins 
ON Coins.id = (SummaryCoins.coin_id) 
WHERE (SummaryCoins.user_id = 1 AND SummaryCoins.date > '2021-04-01' AND SummaryCoins.date < '2021-05-31') 
GROUP BY Coins.id
 

Как я могу получить суммирование за предыдущий месяц ?

Ответ №1:

Один из способов сделать это-расширить диапазон дат в предложении WHERE, чтобы включить оба месяца (или фактически все три месяца), а затем использовать отфильтрованную агрегацию в списке ВЫБОРА.

 SELECT c.id AS "Coins__id", 
       c.name AS "Coins__name",  
       SUM(sc.get_count) filter (where sc.date >= '2021-03-01' and sc.date < '2021-04-01') AS get_count,
       SUM(sc.get_count) filter (where sc.date >= '2021-04-01' and sc.date < '2021-05-01') AS previous_month_count
FROM coins c
  JOIN summary_coins sc ON c.id = sc.coin_id
WHERE sc.date >= '2021-03-01'  --<< note this includes the "previous" month
  AND sc.date < '2020-05-01'
GROUP BY c.id
 

При работе со значениями меток времени (которые у вас есть, несмотря на вводящее в заблуждение название столбца «дата») рекомендуется использовать один день после окончания желаемого диапазона с < оператором, чтобы вы были уверены, что все значения за последний день включены.

Ответ №2:

CASE WHEN может быть хорошим способом дать решение:

 with sum_coins as (
  select coin_id
       , sum(
           case when date_trunc('month', date) = date_trunc('month', CURRENT_DATE)
                then get_count
                else 0 
                end) get_count
       , sum(
           case when date_trunc('month', date) = date_trunc('month', current_date - interval '1' month)
                then get_count
                else 0
                end) previous_month_count
  from summary_coins group by coin_id
)
select coins.name
     , get_count
     , previous_month_count
  from coins
 inner join sum_coins
    on sum_coins.coin_id = coins.id;
 

А использование date_trunc current_date функции и может обеспечить простой способ получения точных данных за текущий месяц и предыдущий месяц.