Postgresql-запит між діапазонами дат


126

Я намагаюся запитати свій db postgresql, щоб повернути результати, де дата є в певний місяць і рік. Іншими словами, я хотів би всіх цінностей за місяць-рік.

Єдиний спосіб, який мені вдалося зробити це поки що, це такий:

SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN '2014-02-01' AND '2014-02-28'

Проблема в цьому полягає в тому, що я повинен обчислити першу дату та останню дату, перш ніж запитувати таблицю. Чи є простіший спосіб зробити це?

Дякую


Чи є інтервал завжди місячним або, можливо, ви починаєте, можливо, о 15-му, а закінчуєтесь 7-го наступного місяця?
frlan

Відповіді:


202

З датами (і часом) багато речей стають простішими, якщо ви користуєтесь >= start AND < end.

Наприклад:

SELECT
  user_id
FROM
  user_logs
WHERE
      login_date >= '2014-02-01'
  AND login_date <  '2014-03-01'

У цьому випадку вам все одно потрібно обчислити дату початку місяця, який вам потрібен, але це повинно бути прямо вперед будь-якою кількістю способів.

Кінцева дата також спрощена; просто додайте рівно один місяць. Не возитися з 28-м, 30-м, 31-м тощо.


Ця структура також має перевагу в можливості підтримувати використання індексів.


Багато людей можуть запропонувати таку форму, як наведена нижче, але вони не використовують індекси:

WHERE
      DATEPART('year',  login_date) = 2014
  AND DATEPART('month', login_date) = 2

Це включає обчислення умов для кожного окремого рядка таблиці (сканування), а не використання індексу для пошуку діапазону рядків, який буде відповідати (діапазон-пошук).


1
Перший підхід повинен псуватися з місяцями (замість днів) f.ex. 2014-12-01& 2015-01-01. Друге теж можна індексувати, але це не банально, я визнаю - EXTRACT()здається більш сумісним.
pozs

1
Ви можете уникнути обчислень дати у вашій програмі, використовуючи інтервал. наприклад: WHERE login_date> = '2014-02-01' AND login_date <'2014-02-01' :: дата + INTERVAL '1 місяць' Це все ще використовує індекси, спрощуючи ваш код.
baswell


23

На всякий випадок, якщо хтось тут приземлиться ... з 8.1 ви можете просто скористатися:

SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN SYMMETRIC '2014-02-01' AND '2014-02-28'

З документів:

МІЖ СИМЕТРИЧНИЙ - це те саме, що і МЕЖДЕ, за винятком того, що не потрібно, щоб аргумент зліва від AND був меншим або рівним аргументу справа. Якщо це не так, ці два аргументи автоматично поміняються, так що завжди мається на увазі непустий діапазон.


-1
SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN '2014-02-01' AND '2014-03-01'

Між ключовими словами винятково працює на дату. Мається на увазі, що час - на 00:00:00 (тобто опівночі).


-14

Прочитайте документацію.

http://www.postgresql.org/docs/9.1/static/functions-datetime.html

Я використовував такий запит:

WHERE
(
    date_trunc('day',table1.date_eval) = '2015-02-09'
)

або

WHERE(date_trunc('day',table1.date_eval) >='2015-02-09'AND date_trunc('day',table1.date_eval) <'2015-02-09')    

Хуанітос Індженьє.


2
Це не відповідає точно на питання. Питання задає дати залежно від місяця та року.
Рам
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.