#sql #postgresql
#sql #postgresql
Вопрос:
у меня есть такая таблица
Дата | сумма |
---|---|
2021-01-01 | 100 |
2021-01-15 | 200 |
2021-01-31 | 300 |
2021-02-01 | 400 |
2021-02-15 | 500 |
2021-02-28 | 600 |
2021-03-01 | 700 |
2021-03-02 | 800 |
2021-03-03 | 900 |
и я хочу создать такой отчет
Дата | сумма |
---|---|
2021-01-31 | 300 |
2021-02-28 | 600 |
2021-03-03 | 900 |
Я запутался, как создать запрос для предоставления подобных данных, получить сумму за каждую последнюю дату месяца.
Допустим, я ввел сумму на 4 марта 2021 года, в отчете будут показаны такие данные
Дата | сумма |
---|---|
2021-01-31 | 300 |
2021-02-28 | 600 |
2021-03-04 | 1000 |
Я использую PostgreSQL
Ответ №1:
Чтобы найти самую последнюю запись группы, вы можете использовать DISTINCT ON
:
SELECT DISTINCT ON (date_trunc('month', my_date))
*
FROM mytable
ORDER BY date_trunc('month', my_date), my_date DESC
date_trunc('month', ...)
нормализует дату до первого числа месяца. Таким образом, каждая дата в феврале будет преобразована в'2021-02-01'
. Это можно использовать для группы месяцев- Упорядочивание этих групп по их фактическому
date DESC
, что упорядочивает самую последнюю дату в начало группы месяца.DISTINCT ON
возвращает именно эти записи.
Комментарии:
1. добавлено объяснение
Ответ №2:
Вы можете сделать это с помощью row_number() :
**Schema (PostgreSQL v13)**
CREATE TABLE tablename (
date date,
amount int
);
INSERT INTO tablename VALUES
('2021-01-01', 100),
('2021-01-15', 200),
('2021-01-31', 300),
('2021-02-01', 400),
('2021-02-15', 500),
('2021-02-28', 600),
('2021-03-01', 700),
('2021-03-02', 800),
('2021-03-03', 900),
('2021-03-04', 1000);
Запрос #1
select date,amount from
(
select date,amount ,
row_number()over (partition by (extract (year from date)),(extract (month from date )) order by date desc)RN
from tablename
)T
WHERE RN=1;
Дата | сумма |
---|---|
2021-01-31T00:00:00.000Z | 300 |
2021-02-28T00:00:00.000Z | 600 |
2021-03-04T00:00:00.000Z | 1000 |
Комментарии:
1. Извините. Это была опечатка. Исправлено.
2. Поскольку один и тот же месяц может существовать в течение нескольких лет в реальных данных, я использовал год и месяц вместе для разделения по предложениям.
Ответ №3:
select date_trunc('month', date '01 Months'::interval) - '01 Days'::interval, sum(amount)
from tableName
group by date_trunc('month', date '01 Months'::interval) - '01 Days'::interval
order by date_trunc('month', date '01 Months'::interval) - '01 Days'::interval desc