Как сравнивать значения sqlite TIMESTAMP - PullRequest
23 голосов
/ 28 мая 2010

У меня есть база данных Sqlite, в которой я хочу выбрать строки, значение которых в столбце TIMESTAMP находится до определенной даты. Я думаю, это будет просто, но я не могу это сделать. Я пробовал это:

SELECT * FROM logged_event WHERE logged_event.CREATED_AT < '2010-05-28 16:20:55'

и различные варианты, как с функциями даты. Я прочитал http://sqlite.org/lang_datefunc.html и http://www.sqlite.org/datatypes.html, и я ожидаю, что столбец будет числовым типом, и что сравнение будет выполнено по значению метки времени Unix. Очевидно, нет. Кто-нибудь, кто может помочь? Если это имеет значение, я пробую это в Sqlite Expert Personal.

Edit:

Вот описание таблицы типов:

CREATE TABLE [logged_event]
(
[id] INTEGER  NOT NULL PRIMARY KEY,
[created_at] TIMESTAMP,
[name] VARCHAR(64),
[data] VARCHAR(512)
);

И данные испытаний:

INSERT INTO table VALUES(1,'2010-05-28T15:36:56+0200','test','test');
INSERT INTO table VALUES(2,'2010-05-28T16:20:49+0200','test','test');
INSERT INTO table VALUES(3,'2010-05-28T16:20:51+0200','test','test');
INSERT INTO table VALUES(4,'2010-05-28T16:20:52+0200','test','test');
INSERT INTO table VALUES(5,'2010-05-28T16:20:53+0200','test','test');
INSERT INTO table VALUES(6,'2010-05-28T16:20:55+0200','test','test');
INSERT INTO table VALUES(7,'2010-05-28T16:20:57+0200','test','test');

Ответы [ 3 ]

42 голосов
/ 28 мая 2010

Проблема заключается в способе вставки данных в таблицу: синтаксис +0200 не соответствует ни одному из форматов времени SQLite :

  1. YYYY-MM-DD
  2. ГГГГ-ММ-ДД ЧЧ: ММ
  3. ГГГГ-ММ-ДД ЧЧ: ММ: СС
  4. ГГГГ-ММ-ДД ЧЧ: ММ: СС.ССС
  5. YYYY-MM-DDThh: MM
  6. YYYY-MM-DDThh: MM: SS
  7. YYYY-MM-DDThh: ММ: СС.ссс
  8. HH: MM
  9. HH: MM: SS
  10. HH: MM: СС.ссс
  11. сейчас
  12. DDDDDDDDDD

Изменение его для использования формата SS.SSS работает правильно:

sqlite> CREATE TABLE Foo (created_at TIMESTAMP);
sqlite> INSERT INTO Foo VALUES('2010-05-28T15:36:56+0200');
sqlite> SELECT * FROM Foo WHERE foo.created_at < '2010-05-28 16:20:55';
sqlite> SELECT * FROM Foo WHERE DATETIME(foo.created_at) < '2010-05-28 16:20:55';
sqlite> INSERT INTO Foo VALUES('2010-05-28T15:36:56.200');
sqlite> SELECT * FROM Foo WHERE DATETIME(foo.created_at) < '2010-05-28 16:20:55';
2010-05-28T15:36:56.200

Если вы абсолютно не можете изменить формат, когда он вставлен, вам может потребоваться сделать что-то «умное» и изменить фактическую строку (т.е. заменить + на . и т. Д. ).


(оригинальный ответ)

Вы не описали, какие данные содержатся в столбце CREATED_AT. Если это действительно datetime, он будет правильно сравниваться со строкой:

sqlite> SELECT DATETIME('now');
2010-05-28 16:33:10
sqlite> SELECT DATETIME('now') < '2011-01-01 00:00:00';
1

Если она хранится как метка времени Unix, вам нужно вызвать функцию DATETIME со вторым аргументом как 'unixepoch' для сравнения со строкой:

sqlite> SELECT DATETIME(0, 'unixepoch');
1970-01-01 00:00:00
sqlite> SELECT DATETIME(0, 'unixepoch') < '2010-01-01 00:00:00';
1
sqlite> SELECT DATETIME(0, 'unixepoch') == DATETIME('1970-01-01 00:00:00');
1

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

1 голос
/ 28 мая 2010

Поддержка SQLite для типов даты / времени очень ограничена. Возможно, вам придется свернуть свой собственный метод для сохранения информации о времени. По крайней мере, так я и сделал.

Вы можете определить свои собственные хранимые функции для выполнения сравнений с помощью API-интерфейса SQLite create_function ().

0 голосов
/ 18 апреля 2014

Насколько я могу судить, вполне разумно включить спецификатор часового пояса; см. текст "форматы от 2 до 10 можно ..." в http://www.sqlite.org/lang_datefunc.html Однако проблема заключается в том, что только функции даты интерпретируют метки времени как даты. Таким образом, для фактического сравнения вам нужно либо передать временную метку через функцию даты, либо сохранить такие вещи, чтобы сравнение строк работало. Один из подходов состоит в том, чтобы кодировать приложение так, чтобы вы вызывали datetime для каждого вставляемого значения и для каждого литерального значения в операторе выбора. Однако просто не включать часовой пояс, как предполагает существующий ответ, может быть проще во многих приложениях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...