web-dev-qa-db-fra.com

Comment comparer les valeurs sqlite TIMESTAMP

J'ai une base de données SQLite dans laquelle je veux sélectionner des lignes dont la valeur dans une colonne TIMESTAMP est antérieure à une certaine date. Je penserais que cela est simple mais je ne peux pas le faire. J'ai essayé ceci:

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

et diverses variations, comme avec les fonctions de date. J'ai lu http://sqlite.org/lang_datefunc.html et http://www.sqlite.org/datatypes.html et je m'attendrais à ce que la colonne soit de type numérique, et que la comparaison serait faite sur la valeur de timestamp unix. Apparemment pas. Quelqu'un qui peut aider? Si cela compte, j'essaie cela dans Sqlite Expert Personal.

Modifier:

Voici la description de la table des types:

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

Et les données de test:

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');
22
Roel

Le problème est lié à la manière dont vous avez inséré les données dans votre table: la syntaxe +0200 ne correspond à aucun des formats de temps de de SQLite :

  1. AAAA-MM-JJ
  2. AAAA-MM-JJ HH: MM
  3. AAAA-MM-JJ HH: MM: SS
  4. AAAA-MM-JJ HH: MM: SS.SSS
  5. AAAA-MM-JJTHH: MM
  6. AAAA-MM-JJTHH: MM: SS
  7. AAAA-MM-JJTHH: MM: SS.SSS
  8. HH: MM
  9. HH: MM: SS
  10. HH: MM: SS.SSS
  11. à présent
  12. DDDDDDDDDD 

Le changer pour utiliser le format SS.SSS fonctionne correctement:

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

Si vous ne pouvez absolument pas modifier le format lorsqu’il est inséré, vous devrez peut-être recourir à une méthode "intelligente" et à la modification de la chaîne réelle (par exemple, remplacer le + par un ., etc.).


(réponse originale)

Vous n'avez pas décrit le type de données contenues dans votre colonne CREATED_AT. S'il s'agit bien d'une date/heure, il se comparera correctement à une chaîne:

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

S'il est stocké sous la forme d'un horodatage Unix, vous devez appeler la fonction DATETIME avec le second argument sous la forme 'unixepoch' pour la comparer à une chaîne:

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

Si aucun de ceux-ci ne résout votre problème (et même s’ils le font!), Vous devriez toujours publier des données afin que d’autres personnes puissent reproduire votre problème. Vous devriez même vous sentir libre de créer un sous-ensemble de vos données d'origine qui reproduit toujours le problème.

41
Mark Rushakoff

Le support de SQLite pour les types date/heure est très limité. Vous devrez peut-être utiliser votre propre méthode pour gérer les informations de temps. Au moins, c'est ce que j'ai fait.

Vous pouvez définir vos propres fonctions stockées pour effectuer des comparaisons à l'aide de l'API SQLite create_function ().

1
J. Polfer

Autant que je sache, il est tout à fait raisonnable d'inclure un spécificateur de fuseau horaire; voir le texte "formats 2 à 10 possible..." at http://www.sqlite.org/lang_datefunc.html Cependant, le problème est que seules les fonctions de date interprètent les horodatages comme des dates. Ainsi, pour une comparaison réelle, vous devez soit transmettre l’horodatage à une fonction de date, soit enregistrer des éléments tels que la comparaison de chaînes fonctionne: valeur littérale dans une instruction select . Cependant, ne pas inclure le fuseau horaire comme suggéré par la réponse existante peut être plus facile dans de nombreuses applications.

0
Sam Hartman