Как сопоставить целый день с полем даты и времени?

У меня есть стол для спичек. В таблице есть столбец с именем matchdate, который является полем datetime.

Если у меня будет 3 матча 01.12.2011:

  • 2011-12-01 12:00:00
  • 2011-12-01 13:25:00
  • 2011-12-01 16:00:00

Как мне это запросить? Как запросить все совпадения за одну дату?

Я смотрел date_trunc(), to_char() и т. Д.
Нет ли какой-нибудь "select * where datetime in date" функции?


person Fred Fickleberry III    schedule 12.01.2012    source источник


Ответы (3)


Преобразуйте значение timestamp в date, если вам нужен простой синтаксис. Нравится:

SELECT *
FROM   tbl
WHERE  timestamp_col::date = '2011-12-01';  -- date literal

Однако с большими таблицами это будет быстрее:

SELECT *
FROM   tbl
WHERE  timestamp_col >= '2011-12-01 0:0'    -- timestamp literal
AND    timestamp_col <  '2011-12-02 0:0';

Причина: второй запрос не должен преобразовывать каждое отдельное значение в таблице и может использовать простой индекс в столбце отметки времени. Выражение может быть sargable.

Обратите внимание, исключена верхняя граница (< вместо <=) для правильного выбора.
Вы можете компенсировать это, создав индексировать выражение следующим образом:

CREATE INDEX tbl_ts_date_idx ON tbl (cast(timestamp_col AS date));

Тогда первая версия запроса будет максимально быстрой.

person Erwin Brandstetter    schedule 12.01.2012
comment
Вы можете заставить Rails создать полуоткрытую [2011-12-01, 2011-12-02) версию с .where(:date => '2011-12-01' ... '2011-12-02'), диапазон из 2 точек будет использовать [2011-12-01, 2011-12-02] и BETWEEN. Будет ли PostgreSQL также приводить все к датам при использовании >= и <, или было бы достаточно умен, чтобы знать, что приведение литералов к временным меткам будет иметь тот же эффект и потребует меньше усилий? - person mu is too short; 12.01.2012
comment
@muistooshort: В этом случае Postgres достаточно умен. Это приведет к моему второму запросу. - person Erwin Brandstetter; 13.01.2012

не уверен, что я упускаю здесь что-то очевидное, но я думаю, что вы можете просто

select * from table where date_trunc('day', ts) = '2011-12-01';
person armin walland    schedule 12.01.2012

Просто используйте функцию SQL BETWEEN следующим образом:

SELECT * FROM table WHERE date BETWEEN '2011-12-01' AND '2011-12-02'

Вам может потребоваться включить время в литералы даты, но это должно включать предел любовника и исключать верхний.

Я считаю, что с рельсов можно:

.where(:between => '2011-12-01'..'2011-12-02')
person Eden Townsend    schedule 12.01.2012
comment
Вы бы хотели, чтобы .where(:date => '2011-12-01' ... '2011-12-02'): :date вместо :between и диапазон из трех точек работал с полуоткрытым [2011-12-01, 2011-12-02) интервалом вместо полностью закрытого [2011-12-01, 2011-12-02] интервала. .. оказывается МЕЖДУ в SQL, ... заканчивается использованием пары _8 _ / _ 9_. - person mu is too short; 12.01.2012