#postgresql
#postgresql
Вопрос:
У меня есть столбец с именем, anchor
который является timestamp
. У меня есть строка со значением 30 января 2020 года. Я хочу сравнить это с 29 февраля 2020 года, и это должно дать мне 1 месяц. Даже если это не 30 дней, но у февраля больше нет дней после 29. Я пытаюсь выставлять счета каждый месяц.
Вот моя sql-скрипка —http://sqlfiddle.com /#!17/6906d/2
create table subscription (
id serial,
anchor timestamp
);
insert into subscription (anchor) values
('2020-01-30T00:00:00.0Z'),
('2019-01-30T00:00:00.0Z');
select id,
anchor,
AGE('2020-02-29T00:00:00.0Z', anchor) as "monthsToFeb29-2020",
AGE('2019-02-28T00:00:00.0Z', anchor) as "monthsToFeb28-2019"
from subscription;
Возможно ли получить возраст так, как я говорю?
Мои ожидаемые результаты:
- Для возраста с 30 января 2020 года по 29 февраля 2020 года я ожидаю 1,0 месяца
- Для возраста с 30 января 2020 года по 28 февраля 2019 года я ожидаю -11,0 месяца
- Для возраста с 30 января 2019 года по 29 февраля 2020 года я ожидаю 13,0 месяца
- Для возраста с 30 января 2019 года по 28 февраля 2019 года я ожидаю 1,0 месяца
(вот как библиотека momentjs делает это для тех парней из node / js):
const moment = require('moment');
moment('Jan 30 2019', 'MMM DD YYYY').diff(moment('Feb 29 2020', 'MMM DD YYYY'), 'months', true) === -13.0
moment('Jan 30 2019', 'MMM DD YYYY').diff(moment('Feb 28 2019', 'MMM DD YYYY'), 'months', true) === -1.0
Комментарии:
1.
For age from jan 30 2020 to feb 2 2020 i expect 1.0 month
здесь разница составляет 3 дня, но вы ожидаете 1 месяц? можете ли вы объяснить логику требования? Что я понял, если день больше, чем дата привязки, то вы считаете его месяцем2. Упс @AkhileshMishra я это исправил, я имею в виду 28-е / 29-е.
Ответ №1:
Как насчет:
select round(('2/29/2020'::date - '1/30/2020'::date) / 30.0);
round
-------
1
select round(('02/28/2019'::date - '1/30/2020'::date ) / 30.0);
round
-------
-11
select round(('2/29/2020'::date - '1/30/2019'::date) / 30.0);
round
-------
13
select round(('2/28/2019'::date - '01/30/2019'::date) / 30.0);
round
-------
1
Вычитание даты дает вам целочисленное значение дней, затем вы делите на 30-дневный месяц и округляете до ближайшего целого числа. Вы могли бы поместить это в функцию и использовать это.
Комментарии:
1. Спасибо, Адриан! Это очень приятно, спасибо! Я не думаю, что это идеально соответствует
moment.diff
но я думаю, что это определенно основа, спасибо за это! Принято!2. Ну, moment.diff() выполняет специальную обработку в течение нескольких месяцев / лет разницы . Не уверен, что я согласен с этим, но это то, что есть.
3. Спасибо, что поделились этим! Я не знал об этом. Я попытаюсь имитировать это в postgres. Поскольку это дает мне правильное количество выставленных счетов. Например, если я различаю 30 января 2020 года и 29 февраля 2020 года, это дает мне 1. Это означает, что я должен был выставить счет пользователю дважды при запуске разница.