Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

Consulta con distinct y order by

Estas en el tema de Consulta con distinct y order by en el foro de Mysql en Foros del Web. Hola, estoy muy atascado con una consulta que en principio pensaba que iba a ser sencilla. Mi problema es el siguiente: En la siguiente tabla ...
  #1 (permalink)  
Antiguo 04/06/2013, 16:52
 
Fecha de Ingreso: junio-2013
Mensajes: 2
Antigüedad: 10 años, 10 meses
Puntos: 0
Consulta con distinct y order by

Hola, estoy muy atascado con una consulta que en principio pensaba que iba a ser sencilla. Mi problema es el siguiente:

En la siguiente tabla se insertan comentarios indicando el usuario y la fecha:

Código MySQL:
Ver original
  1. Comentario, Usuario, Fecha
  2. ------------------------------------------------------------
  3. comentario, david, 05/06/2013 23:30  
  4. comentario, jose,  05/06/2013 23:20
  5. comentario, david,    04/06/2013 13:30
  6. comentario,  david,     04/06/2013 13:15
  7. comentario , carlos,    04/06/2013 13:10
  8. comentario ,  david,  04/06/2013 12:30
  9. comentario , ruben,  04/06/2013 12:00
Lo que quiero obtener es el último comentario de cada usuario. Para descartar opciones os explico lo que he probado:
Código MySQL:
Ver original
  1. select distinct(usuario), comentario, fecha from comentarios
Esto no funciona ya que me sigue mostrando los usuarios duplicados.

Código MySQL:
Ver original
  1. select distinct usuario from comentarios
Esta sí que me muestra sólo un campo por usuario, pero no lo ordena por fecha

Código MySQL:
Ver original
  1. select usuario, fecha from comentarios
  2. group by usuario
Tampoco ordena por fecha como debería

¿Alguien puede ayudar a este humilde novato?

Última edición por gnzsoloyo; 04/06/2013 a las 20:00
  #2 (permalink)  
Antiguo 04/06/2013, 20:58
 
Fecha de Ingreso: agosto-2003
Mensajes: 174
Antigüedad: 20 años, 8 meses
Puntos: 3
Respuesta: Consulta con distinct y order by

¿como que la segunda y tercera no ordenan por fecha?


Lo que tu buscas es obtener el último de cada usuario. El ultimo lo obtienes con la función max(fecha) que te devuelve la fecha mas alta. Por tanto si haces una select que devuelva el max del usuario X te devuelve el último del usuario X. Si aplicas eso a todos ya tienes una select que te devuelve el ultimo de cada uno.
Código MySQL:
Ver original
  1. select C.usuario,C.comentario from comentarios C
  2. group by C.usuario
  3. having fecha=
  4.    select max(fecha) from comentario where usuario=C.usuario
Creo que esto funcionará y si no será algo parecido. Mucha gente tiene problemas con el having.

La idea básica es que en una select primero seleccionas registros. Luego puede ir una claúsula where que EXCLUYE registros de la selección. De lo que queda hay una claúsula group que agrupa los datos obtenidos y realiza el cálculo correspondiente si lo hay y por último la claúsula having que EXCLUYE de estos resultados lo que no cumpla la condición del having. Despues de todo esto tienes la posibilidad de ORDENAR con un order by.

En el caso presente pongo un alias C a la tabla comentarios y hago una select de todos los usuarios. Al agrupar por usuario me quedará cada usuario con todos sus comentarios. En el having excluyo de cada grupo aquellos que no cumplan la condición de que la fecha tiene que ser la mayor. De esta forma solo quedsrá uno de cada grupo con la fecha mayor en cada caso. Es poco ortodoxo porque he utilizado una alias para poder subpreguntar a una tabla sobre si misma, pero creo que funcionará.

Última edición por gnzsoloyo; 05/06/2013 a las 19:20
  #3 (permalink)  
Antiguo 05/06/2013, 08:20
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Consulta con distinct y order by

Hola ivan89:

hay varios detalles en tus consultas, que supongo que son por desconocimiento de cómo funciona el operador DISTINCT...

La función DISTINCT omite los registros repetidos, el detalle está en que un registro repetido es aquel DONDE TODOS SUS CAMPOS SON EXACTAMENTE IGUALES... cuando haces un

Código:
... DISTINCT usuario FROM ...
la consulta funciona porque SÓLO ESTÁ CONSIDERANDO LA COLUMNA USUARIO...

cuando haces un

Código:
... DISTINCT usuario, comentario, fecha ...
Estás comparando LOS TRES CAMPOS... conque uno solo de ellos SEA DISTINTO, entonces se mostrará en la consulta.

Ahora bien, la idea del GROUP BY no está tan errada, sin embargo DEBES HACER USO DE FUNCIONES DE AGRUPACIÓN (MIN, MAX, COUNT, etc.)... es cuestión de que practiques un poco más.

Ahora si, volviendo al problema original... en realidad este tipo de consultas es de las más comunes en SQL, hay muchos ejemplos en este foro o en la red para resolverlo, y en realidad existen muchas formas para hacerlo... con IN, con EXISTS, con HAVING (como propone Gedeon). Sin embargo una de las maneras más sencillas y desde mi punto de vista la que mejor rendimiento tiene es hacerlo con una subconsulta. veamos el ejemplo, con los datos que tienes en tu tabla:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM tabla;
  2. +------------+---------+---------------------+
  3. | comentario | Usuario | Fecha               |
  4. +------------+---------+---------------------+
  5. | comentario | david   | 2013-06-05 23:30:00 |
  6. | comentario | jose    | 2013-06-05 23:20:00 |
  7. | comentario | david   | 2013-06-04 13:30:00 |
  8. | comentario | david   | 2013-06-04 13:15:00 |
  9. | comentario | carlos  | 2013-06-04 13:10:00 |
  10. | comentario | david   | 2013-06-04 12:30:00 |
  11. | comentario | ruben   | 2013-06-04 12:00:00 |
  12. +------------+---------+---------------------+
  13. 7 rows in set (0.00 sec)


Como te interesa el ÚLTIMO comentario de cada usuario, utilizas la función MAX y la cláusula GROUP BY, así:

Código MySQL:
Ver original
  1. mysql> SELECT usuario, MAX(fecha) FROM tabla GROUP BY usuario;
  2. +---------+---------------------+
  3. | usuario | MAX(fecha)          |
  4. +---------+---------------------+
  5. | carlos  | 2013-06-04 13:10:00 |
  6. | david   | 2013-06-05 23:30:00 |
  7. | jose    | 2013-06-05 23:20:00 |
  8. | ruben   | 2013-06-04 12:00:00 |
  9. +---------+---------------------+
  10. 4 rows in set (0.00 sec)

Ahora bien, si también necesitas extaer el comentario que corresponde o algún otro dato, de tu tabla, puedes hacer un INNER JOIN para filtrar la información a partir de esta consulta, así:

Código MySQL:
Ver original
  1. mysql> SELECT T1.*
  2.     -> FROM tabla T1
  3.     -> INNER JOIN
  4.     -> (  SELECT usuario, MAX(fecha) max_fecha
  5.     ->    FROM tabla
  6.     ->    GROUP BY usuario) T2
  7.     -> ON T1.usuario = T2.usuario AND T1.fecha = T2.max_fecha;
  8. +------------+---------+---------------------+
  9. | comentario | Usuario | Fecha               |
  10. +------------+---------+---------------------+
  11. | comentario | david   | 2013-06-05 23:30:00 |
  12. | comentario | jose    | 2013-06-05 23:20:00 |
  13. | comentario | carlos  | 2013-06-04 13:10:00 |
  14. | comentario | ruben   | 2013-06-04 12:00:00 |
  15. +------------+---------+---------------------+
  16. 4 rows in set (0.00 sec)

Dale un vistazo y cualquier duda la comentas en el foro y con gusto tratamos de ayudarte.

Saludos
Leo.
  #4 (permalink)  
Antiguo 05/06/2013, 16:07
 
Fecha de Ingreso: junio-2013
Mensajes: 2
Antigüedad: 10 años, 10 meses
Puntos: 0
Respuesta: Consulta con distinct y order by

Bien, antes que nada muchísimas gracias por la ayuda.

Gedeon, lo que me propones me devuelve un error, supongo que por igualar el Having a la subconsulta. He probado poniéndola entre paréntesis y nada, me da error.

Leo, tu método no funcionaba correctamente. Puede que con los campos de ejemplo que yo puse sí, pero en la tabla real que tiene muchos más registros no ordenaba correctamente. Lo he solucionado poniendo un ORDER BY t1.fecha desc.

Por lo tanto quedaría:
Código MySQL:
Ver original
  1. mysql> SELECT T1.*
  2.     -> FROM tabla T1
  3.     -> INNER JOIN
  4.     -> (  SELECT usuario, MAX(fecha) max_fecha
  5.     ->    FROM tabla
  6.     ->    GROUP BY usuario) T2
  7.     -> ON T1.usuario = T2.usuario AND T1.fecha = T2.max_fecha
  8.     -> ORDER BY T1.fecha desc
  9.     --> LIMIT 15;

Última edición por gnzsoloyo; 05/06/2013 a las 19:20
  #5 (permalink)  
Antiguo 06/06/2013, 08:14
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Consulta con distinct y order by

Hola ivan89:

Cita:
Leo, tu método no funcionaba correctamente
Al final de cuentas el método funciona, que no ordene la información es otra cosa

No esperes encontrar en este foro una consulta que te sirva sólo con copiar y pegar, en la mayoría de los casos tendrás que hacer ajustes, pues aquí solo se dan guías para obtener lo que quieres.

En fin, me da gusto que te haya servido el código.

Saludos
Leo.

Etiquetas: distinct
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 09:14.