2012-10-05 26 views
6

Vi un tipo similar de preguntas aquí, pero ninguna de ellas ayudó a mi situación.MySQL Group by ID y Latest Datetime

Tengo una tabla digamos prueba (usando MyISAM MySQL)

prueba tiene el siguiente esquema:

TID INT PRIMARY KEY AUTO_INCREMENT 
    TData varchar (data that i want to select) 
    TUserID INT (this will be joined with users table, same users can have many records here) 
    TViewedAt DATETIME (records each time user visits page, datetime format) 

Ahora, cada vez que una página de prueba es visitada por usuario actualmente conectado, se añade registros a esta tabla se registra la identificación del usuario que visitó, algunos datos y la fecha y la hora que el usuario visitó con el TID se incrementa automáticamente cada vez.

Luego tengo una página de administración de back-end donde puedo ver qué página de prueba visitó el usuario, cuántas veces, datos y cuándo. Básicamente es una tabla con una lista de 20-25 últimas filas. My Query solo debe seleccionar un registro por datos. Los datos pueden ser los mismos para el usuario pero en diferentes momentos, pero solo quiero seleccionar un dato para cada usuario que sea el más reciente. Por lo tanto, si el usuario visitó la página de prueba 10 veces, 10 registros irán a la base de datos pero mostrarán solo 1 registro más reciente en la tabla. Si otro usuario visita la página 15 veces, muestra 1 registro para este segundo usuario, que es el último nuevamente, así que en total ahora tenemos 2 filas en la mesa. Tengo todo para trabajar pero GROUP BY por alguna razón y MAX (fecha) no me da la última fecha y hora para cada fecha.

aquí es mi consulta:

SELECT * 
    FROM Test 
    WHERE TUserID = 123 
    GROUP BY TData 
    ORDER BY TViewedAt 

retornos 2 filas fuera de las cuales ninguna de esas filas son los últimos.

muchas gracias

Respuesta

11

Creo que con lo siguiente puede lograr lo que necesita, estas operaciones se denominan "Grupo-sabio máximo".

Opción 1

Esta es la más fácil de entender, una subconsulta devolverá máxima TID para todos los usuarios ya que el max se utiliza en conjunto con Group By y que nosotros otro consulta para obtener todos los datos para esas ID.

Select TID, TData, TUserID, TViewedAt 
From Test 
Where TID In(
    Select Max(TID) 
    From Test 
    Group By TUserID 
) 

Opción 2

poco más complejo de entender, pero lo más probable es más eficiente, esto funciona sobre la base de que cuando t1.TViewedAt está en su valor máximo, no hay t2.TViewedAt con un valor mayor y los valores de las filas t2 serán NULL.

SELECT t1.TID, t1.TData, t1.TUserID, t1.TViewedAt 
FROM Test t1 
LEFT JOIN Test t2 ON t1.TUserID = t2.TUserID AND t1.TViewedAt < t2.TViewedAt 
WHERE t2.TUserID IS NULL; 

Resultado

TID TData TUserID TViewedAt 
4 test3 123  2012-10-05 00:00:00.000 
5 test2 213  2012-10-03 00:00:00.000 
+0

sí, funciona, muchas gracias, muy simple y fácil – Giorgi

+0

bienvenida, me complace ayudar –

+1

¿hay alguna manera de hacerlo? eso es más eficiente, es decir, no requiere subconsultas? me estoy dando cuenta de que está matando mi servidor – Jason

1

Se necesitan GROUP BY TUserID para el agregado máx.

SELECT 
    TID, 
    TData, 
    main.TUserID 
    main.TViewedAt 
FROM 
    yourTable main 
    JOIN ( 
    SELECT TUserID, MAX(TViewedAt) AS TViewedAT FROM yourTable GROUP BY TUserID 
) tmax ON main.TUserID = tmax.TUserID AND main.TViewedAt = tmax.TViewedAt 

Este es un método portátil que se une a una subconsulta. La subconsulta extrae la última TUserID,TViewedAt por usuario, y se une a la tabla principal para extraer el TData que coincida.

Si sólo desea un usuario al mismo tiempo, que puede hacer:

SELECT 
    TData, 
    TViewedAt 
FROM yourTable 
WHERE TUserID = 'someid' 
GROUP BY TUserId 
HAVING TViewedAt = MAX(TViewedAt) 

Lo anterior sólo funcionará en MySQL de la manera que lo he escrito sin embargo. Otro RDBMS se quejará del hecho de que TData aparece en la lista SELECT pero no está en el GROUP BY.

+0

la segunda vez que lo intenté y devuelto 0 filas. TViewed ¿En el formato DATETIME MAX entiende eso? – Giorgi

+1

@Giorgi MAX() entiende las columnas de fecha y hora. Use el primero pero agregue una cláusula WHERE para limitar el usuario que desea. El primero es el mejor y más portátil de los dos. –

0
SELECT t1.TData, t1.TUserID, t1.TViewedAt 
FROM Test t1 
JOIN 
(SELECT TUserID, MAX(TViewedAt) 
FROM Test 
GROUP BY TUserID) t2 
ON t1.TUserID = t2.TUserID AND t1.TViewedAt=t2.TViewedAt 
+0

que no funcionó :( – Giorgi

+0

Lo sentimos, perdimos que TData puede ser diferente. Luego ver actualizaciones ... – alex

1

siguiente consulta, puede ayudar a You-

select * from pages where date(create_date)=(select date(create_date) from pages order by create_date limit 1) 
+1

¿Podría explicarnos cómo responde esto a la pregunta? – Braiam