2008-12-24 18 views
10

En pocas palabras, tengo una tabla con, entre otras cosas, una columna para marcas de tiempo. Quiero obtener la fila con la marca de tiempo más reciente (es decir, el valor más grande). Actualmente estoy haciendo esto:Agregue funciones en la cláusula WHERE en SQLite

SELECT * FROM table ORDER BY timestamp DESC LIMIT 1 

Pero yo preferiría hacer algo como esto:

SELECT * FROM table WHERE timestamp=max(timestamp) 

Sin embargo, SQLite rechaza esta consulta:

SQL error: misuse of aggregate function max() 

El documentation confirma esta comportamiento (parte inferior de la página):

Las funciones agregadas solo se pueden usar en una instrucción SELECT.

Mi pregunta es: ¿es posible escribir una consulta para obtener la fila con la mayor marca de tiempo sin pedir la selección y la limitación del número de filas devueltas a 1? Parece que debería ser posible, pero supongo que mi SQL-fu no está preparado.

Respuesta

16
SELECT * from foo where timestamp = (select max(timestamp) from foo) 

o, si SQLite insiste en tratar subselects como conjuntos,

SELECT * from foo where timestamp in (select max(timestamp) from foo) 
+0

Funciona muy bien, gracias. Sabía que tenía que ser algo simple. –

+0

Simplemente curioso, ¿la subconsulta causa que sqlite procese la tabla dos veces, o está optimizada? –

+0

Hace que procese la tabla dos veces: una para encontrar el máximo y otra para encontrar las coincidencias.No estoy seguro de que pueda obtener el algoritmo de una pasada para esto de SQL. – SquareCog

1

Creo que he respondido a esta pregunta 5 veces en la semana pasada ahora, pero estoy demasiado cansado para encontrar una enlace a uno de los ahora mismo, así que aquí está de nuevo ...

SELECT 
    * 
FROM 
    table T1 
LEFT OUTER JOIN table T2 ON 
    T2.timestamp > T1.timestamp 
WHERE 
    T2.timestamp IS NULL 

básicamente, se está buscando la fila donde ninguna otra fila coincide con que es posterior a la misma.

NOTA: Como se señala en los comentarios, este método no funcionará tan bien en este tipo de situación. Por lo general, funcionará mejor (al menos para SQL Server) en situaciones en las que desee la última fila para cada cliente (como ejemplo).

+0

Eso podría funcionar, pero no hacer una unión ¿incurrir en alguna penalización de rendimiento? –

+1

Esto funciona, pero es increíble en su ineficiencia. Suponiendo 10 filas en la tabla original, esto produce (y descarta) 55 filas. Para 100 filas, el tamaño del conjunto que está produciendo es 5.050. Crece muy rápido. Mejor solo hacer los dos escaneos. – SquareCog

+0

Ah, y esto no funciona cuando tienes dos filas con la misma marca de tiempo máxima. – SquareCog

1

puede simplemente hacer

SELECT *, máx (fecha y hora) de la tabla

Editar: Como función de agregado no puede ser utilizado como esto por lo que da error. Creo que lo SquareCog había sugerido era el mejor que puede hacer

SELECT * FROM table WHERE timestamp = (select max(timestamp) from table) 
4

Hay muchas maneras de pelar un gato.

Si tiene una Columna de identidad que tiene una funcionalidad de incremento automático, una consulta más rápida resultaría si devuelve el último registro por ID, debido a la indexación de la columna, a menos que, por supuesto, desee poner un índice en la columna de marca de tiempo.

SELECT * FROM TABLE ORDER BY ID DESC LIMIT 1