2016-09-27 4 views
1

Как найти все записи пользователя, созданные ровно несколько месяцев назад/месяц в Postgres SQL? Является ли это возможным?Как найти пользователей, созданных в течение нескольких месяцев/кварталов назад в Postgres SQL?

В Postgres, вы можете найти дату, которая ровно 1 месяц от поля даты и времени, как:

select created_at + interval '1 month' from users limit 1; 
?column?   
---------------------------- 
2016-10-05 17:05:14.811537 
(1 row) 

Если сегодня 9/27/2016, я хочу найти все пользователя записи, созданные 7/27/2016, 7/27/2016, 6/27/2016, ... 1/27/2015 и т. д. и т. д. Как это сделать в SQL?

Обратите внимание, что это не просто сравнение даты из-за того, что некоторые месяцы имеют 31 день, а другие - 28, 29, 30 дней.

Если сегодня 28.02.2012 (не-високосный год), я хочу, чтобы все пользователи создали в следующие даты: 1/28/2015, 1/29/2015, 1/30/2015, 1/31/2015, 12/28/2014, 12/29/2014, 12/30/2014, 12/31/2014 и т. Д.

Если сегодня 28.02.2012 (високосный год), я хочу все пользователи, созданные в следующие даты: 1/28/2015, 12/28/2014, 11/28/2014 и т. д. (но не на 1/29/2015, 1/30/2015, 1/31/2015, так как эти пользователи будут подняты на следующий день, см. Ниже).

Если сегодня 2/29/2016 (високосный год), я хочу, чтобы все пользователи создали в следующие даты: 1/29/2015, 1/30/2015, 1/31/2015, 12/29/2014, 12/30/2014, 12/31/2014 и т. Д.

Если сегодня 3/31/2016, я хочу, чтобы все пользователи были созданы 31.12.2015, 31.01.2016, но никого не создавали в феврале 2016 года, потому что они были бы выбраны в предыдущие дни марта 2016 года.

Как сделать это выше с кварталами, а не месяцами?

Другой вопрос, связанный с этим, - это производительность. Если я создам индекс на created_at, можно ли избежать сканирования всего стола, если я сделаю этот тип запросов?

спасибо.

ответ

1

Ну ... Если вы думаете об этом, вы хотите сравнить число дней в действительности, не так ли? Поэтому вы должны сделать именно это:

select 
    * 
from 
    users 
where 
    date_part('day', created_at) = date_part('day', current_timestamp) 
    OR 
    (
    -- Check if this is the last day of month 
     extract(month from current_timestamp + '1day'::interval) <> extract(month from current_timestamp) 
     AND 
     date_part('day', created_at) > date_part('day', current_timestamp) 
    ) 
limit 
    1 
; 

И в отношении вашего указательного вопроса - да.

Вдохновение для проверки последнего дня месяца, взятого с here.

В принципе, если я все еще не получу Ваше требование, вы должны иметь возможность легко изменить свой код, чтобы его встретить, если вы его понимаете. :)

+0

Это не так просто. Если сегодня 2/28/2015, я хочу, чтобы пользователи были созданы на 1/28/2015, 1/29/2015, 1/30/2015, 1/31/2015 и т. Д. Но если сегодня это 2/28/2016, Я хочу, чтобы пользователи были созданы на 1/28/2016 и т. Д., Но не на 1/29/2016. Если сегодня 21.02.2016, я хочу, чтобы пользователи создали 1/29/2016, 1/30/2016, 1/31/2016 и т. Д. Поскольку месяцы имеют разное количество дней, мы должны округлить его так, чтобы говорить. –

+0

Добавлена ​​коррекция в соответствии с вашим требованием. –

+0

Если сегодня 28.02.2015, я не уверен, работает ли ваш код. Кроме того, если сегодня 4/30/2016, ему нужны пользователи, созданные 30.01.2012, 1/31/2016. Где эта логика? –

Смежные вопросы