2010-05-28 22 views
21

Tengo una base de datos Sqlite en la que quiero seleccionar filas cuyo valor en una columna TIMESTAMP es anterior a una fecha determinada. Creo que esto es simple, pero no puedo hacerlo. He intentado esto:Cómo comparar valores sqlite TIMESTAMP

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

y diversas variaciones sobre el mismo, al igual que con las funciones de fecha. He leído http://sqlite.org/lang_datefunc.html y http://www.sqlite.org/datatypes.html y esperaba que la columna fuera de tipo numérico y que la comparación se hiciera en el valor de la marca de tiempo de Unix. Aparentemente no. ¿Alguien que pueda ayudar? Si es importante, estoy probando esto en Sqlite Expert Personal.

Editar:

Aquí está Tipo Descripción tabla:

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

Y los datos de prueba:

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'); 
+0

¿Qué versión de SQLite está ejecutando? La documentación 3.x.x no define en qué afinidad se basa una columna llamada TIMESTAMP. http://sqlite.org/datatype3.html –

+1

Sqlite 3. Como todo lo que no está en un conjunto limitado de tipos de texto (TEXTO, BLOB, algunos otros) es numérico, de acuerdo con la documentación, asumí que TIMESTAMP sería un tipo numérico. De nota es que estoy creando esta tabla a través del asignador de ORM de Propel, y es una tabla autogenerada, por lo que no puedo cambiar fácilmente a otro tipo. Supongo que si pudiera hacer que esta columna se comportara como DATETIME, estaría a mitad de camino. – Roel

Respuesta

36

el problema es con la forma en que haya insertado los datos en la tabla: la sintaxis +0200 no coincide con ninguna de :

  1. AAAA-MM-DD
  2. AAAA-MM-DD HH : MM
  3. AAAA-MM-DD HH: MM: SS
  4. AAAA-MM-DD HH: MM: sS.sss
  5. AAAA-MM-DDTHH: MM
  6. AAAA-MM-DDTHH: MM : SS
  7. AAAA-MM-DDTHH: MM: SS.sss
  8. HH: MM
  9. HH: MM: SS
  10. HH: MM: SS.sss
  11. ahora
  12. DDDDDDDDDD

Si lo cambia a utilizar el formato sS.sss funciona correctamente:

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 no puede cambiar el formato cuando se lo inserta, es posible que deba volver a hacer algo "inteligente" y modificar la cadena real (es decir, para reemplazar el + con un ., etc.).


(respuesta original)

No ha descrito qué tipo de datos se encuentran, en su columna CREATED_AT.Si en verdad una fecha y hora, comparará correctamente contra una cadena:

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

si se almacena como una marca de tiempo Unix, es necesario llamar a DATETIME función con el segundo argumento como 'unixepoch' el que comparar una cadena:

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 ninguno de los que resuelve su problema (e incluso si lo hacen!) que debe siempre colocar algunos datos para que otras personas puedan reproducir su problema. Incluso debe tener la libertad de encontrar un subconjunto de sus datos originales que aún reproduzca el problema.

+0

Sí, también vi estos ejemplos en el manual. Lo que quiero hacer es SELECCIONAR * de la tabla DONDE columna <'2010-05-23 14:32:29'; y supongo que necesito agregar una función allí en algún lugar de alguna forma, pero no tengo idea de cómo. – Roel

+1

Gracias, de hecho, el especificador de zona horaria lo hizo. Esto fue exacerbado por Sqlite Expert al no mostrar esa parte; solo apareció cuando hice una línea de comando SELECT para publicar los datos de la prueba aquí. Hackeé una solución en mi programa para dejar afuera la parte de la zona horaria. – Roel

1

apoyo de SQLite para este tipo de fecha/hora es muy limitado. Es posible que deba usar su propio método para mantener la información del tiempo. Al menos, eso es lo que hice.

Puede definir sus propias funciones almacenadas para hacer comparaciones utilizando la API SQLite create_function().

+0

Tenga en cuenta que el problema que tuve involucró _adding_ períodos de tiempo, sin embargo, no comparando. Creo que la respuesta de Mark es probablemente mejor en esta situación. –

0

Lo mejor que puedo decir es que es completamente razonable incluir un especificador de zona horaria; vea el texto "formatos 2 a 10 puede ..." en http://www.sqlite.org/lang_datefunc.html Sin embargo, el problema es que solo las funciones de fecha interpretan las marcas de tiempo como fechas. Por lo tanto, para una comparación real, debe pasar la marca de tiempo a través de una función de fecha o almacenar cosas tales que la comparación de cadenas funcione. Un enfoque sería codificar su aplicación de manera que llamara a la fecha y hora en cada valor que inserta y en cada valor literal en una declaración de selección. Sin embargo, simplemente no incluir el huso horario sugerido por la respuesta existente puede ser más fácil en muchas aplicaciones.

Cuestiones relacionadas