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

Agupar por dos columnas, un poco diferente

Estas en el tema de Agupar por dos columnas, un poco diferente en el foro de Bases de Datos General en Foros del Web. Alguien sabe como se podria ordenar por dos campos para el siguiente problema? Tengo una tabla de fotos (ID, FECHA, ID_USUARIO, RUTA) y una tabla ...
  #1 (permalink)  
Antiguo 15/06/2011, 11:59
 
Fecha de Ingreso: junio-2009
Mensajes: 309
Antigüedad: 15 años, 5 meses
Puntos: 5
Agupar por dos columnas, un poco diferente

Alguien sabe como se podria ordenar por dos campos para el siguiente problema?

Tengo una tabla de fotos (ID, FECHA, ID_USUARIO, RUTA) y una tabla de fotos_etiquetas (ID_FOTO, FECHA, ID_USUARIO) que sirve para etiquetarse en la foto.

Necesito sacar en una consulta las ultimas 5 fotos donde sale o ha subido ordenadas descendentemente por fotos.fecha y fotos_etiquetas.fecha

Es decir que si etiquetan a un usuario en una foto tiene que salir antes que una foto que haya subido.

La consulta que tengo es la siguiente
Código SQL:
Ver original
  1. SELECT f.ID, f.FECHA
  2.  FROM fotos f, fotos_etiquetas fe
  3. WHERE ((f.ID_USUARIO = 1) OR (fe.ID_USUARIO = 1 AND fe.ID_FOTO = f.ID))
  4. GROUP BY f.ID
  5. ORDER BY f.FECHA DESC, fe.FECHA
  6. LIMIT 5

Pero claro, ahora lo que hace es ordenar por f.FECHA, y los repetidos tomaria fe.FECHA para saber cual pone primero. Y yo necesito que combine ambas.

Alguna idea??
  #2 (permalink)  
Antiguo 17/06/2011, 05:03
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 8 meses
Puntos: 574
Respuesta: Agupar por dos columnas, un poco diferente

Código MySQL:
Ver original
  1. SELECT sbc.ID as ID, sbc.FECHA as Fecha,Sbc.tipo
  2. FROM (SELECT f.ID as ID, f.FECHA as Fecha, 1 as Tipo
  3.               FROM fotos f
  4.               WHERE f.ID_USUARIO=1
  5.               ORDER BY f.FECHA DESC LIMIT 5
  6.            UNION ALL
  7.              SELECT fe.ID_FOTO as ID, fe.FECHA as Fecha, 0 as Tipo
  8.                 FROM fotos_etiquetas fe
  9.                 WHERE fe.ID_USUARIO=1
  10.                 ORDER BY fe.FECHA DESC LIMIT 5) as Sbc
  11. ORDER BY Sbc.fecha DESC,Sbc.tipo ASC

Creo?

es decir primero buscas las 5 ultimas subidas por el usuario y les agregas un campo tipo=1, luego buscas las ultimas 5 donde el usuario ha sido etiquetado y les agregas tipo=0, unes los dos resultados los reordenas por fecha y tipo y eliges los ultimos 5 ....

Es posible que se te repita una foto puesto ya que si la ha subido y ha sido etiquetado la foto puede estar en los dos conjuntos....

Para evitar eso debes decidir que hay que hacer eliminar las que esten en el primer grupo o en el segundo...

Código MySQL:
Ver original
  1. SELECT sbc.ID as ID, sbc.FECHA as Fecha,Sbc.tipo
  2. FROM (SELECT f.ID as ID, f.FECHA as Fecha, 1 as Tipo
  3.               FROM fotos f
  4.               WHERE f.ID_USUARIO=1
  5.               AND f.ID NOT IN (SELECT fe1.ID_FOTO
  6.                                             FROM fotos_etiquetas fe1
  7.                                             WHERE fe1.ID_USUARIO=1
  8.                                             ORDER BY fe1.FECHA DESC LIMIT 5)
  9.               ORDER BY f.FECHA DESC LIMIT 5
  10.            UNION ALL
  11.              SELECT fe.ID_FOTO as ID, fe.FECHA as Fecha, 0 as Tipo
  12.                 FROM fotos_etiquetas fe
  13.                 WHERE fe.ID_USUARIO=1
  14.                 ORDER BY fe.FECHA DESC LIMIT 5) as Sbc
  15. ORDER BY Sbc.fecha DESC,Sbc.tipo ASC

Así eliminados de las subidas las que ya esten en las etiquetadas... seguiremos teniendo un conjunto de mas de 5 fotos con lo que seguro que funciona...

tipo solo sirve para ordenar no para saber si la foto la ha subido o no un usuario... puesto que si la ha subido y ha sido etiquetado en ella saldrà con tipo = 0
__________________
Quim
--------------------------------------------------
Ayudar a ayudar es una buena práctica!!! Y da buenos resultados.

Última edición por quimfv; 17/06/2011 a las 05:26
  #3 (permalink)  
Antiguo 17/06/2011, 16:59
 
Fecha de Ingreso: junio-2009
Mensajes: 309
Antigüedad: 15 años, 5 meses
Puntos: 5
Respuesta: Agupar por dos columnas, un poco diferente

Madre mia que pedazo consulta!! O.o, esto ya se escapa de mis conocimientos jajaja, aunque la comprendo.

1 pregunta:

¿Usar union provoca producto cartesiano (creo que se llama asi) , eso que no es nada recomendable en las consultas?

Muchas graciaaaas!! ;)
  #4 (permalink)  
Antiguo 17/06/2011, 20:01
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: Agupar por dos columnas, un poco diferente

No. El producto carteisano sólo ocurre con el JOIN. El UNION es el encadenamiento de resultados.
En esencia, el primero es A x B, mientras que el segundo es {A; B}
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #5 (permalink)  
Antiguo 17/06/2011, 20:47
 
Fecha de Ingreso: junio-2009
Mensajes: 309
Antigüedad: 15 años, 5 meses
Puntos: 5
Respuesta: Agupar por dos columnas, un poco diferente

aclarado!, lo que entonces si join crea un producto cartesiano.... entiendo entonces que tanto left join y right join lo hacen... :S, creo que estoy teniendo un montoooooooon de productos cartesianos que no se como evitar... :S

Voy a ver si consigo adaptar esta consulta a mi caso.
Un saludo!
  #6 (permalink)  
Antiguo 18/06/2011, 10:33
 
Fecha de Ingreso: junio-2009
Mensajes: 309
Antigüedad: 15 años, 5 meses
Puntos: 5
Respuesta: Agupar por dos columnas, un poco diferente

A ver, comento los resultados.
He adaptado la consulta a mi caso real, y habian un par de fallos insignificantes.

1. No puede haber limit en el IN
Código SQL:
Ver original
  1. AND f.ID NOT IN (SELECT fe1.ID_FOTO
  2.                                             FROM fotos_etiquetas fe1
  3.                                             WHERE fe1.ID_USUARIO=1
  4.                                             ORDER BY fe1.FECHA DESC LIMIT 5)

2. Al parecer, al usar UNION ALL, no se puede usar en cada una de las consultas el ORDER BY y el LIMIT. Se utilizaria el order by y el limit del final del SQL.



El resultado final de mi consulta adaptandola a mis tablas ha quedado .... "Increible" jjajaa. Puede que no la comprendais por la estructura que uso en mis tablas. Arriba simplifiqué la estructura para hacerlo mas simple.

Código SQL:
Ver original
  1. SELECT sbc.ID, sbc.FECHA, sbc.RUTA, sbc.EXTENSION, fd.ID_FOTO, fd.NOMBRE_FICHERO
  2.                 FROM (SELECT f.ID AS ID, f.RUTA, f.EXTENSION, f.FECHA AS FECHA, 1 AS TIPO, FECHA AS FECHA_ORDEN
  3.                       FROM fotos f
  4.                       WHERE f.ID_SECCION = 8 AND f.ID_ELEMENTO= $id_usuario
  5.                       AND f.ID NOT IN (SELECT fe1.ID_FOTO
  6.                                        FROM fotos_etiquetas fe1
  7.                                        WHERE fe1.ID_A_QUIEN_ETIQUETA = $id_usuario
  8.                                        ORDER BY fe1.FECHA DESC)
  9.                       UNION ALL
  10.                       SELECT fe.ID_FOTO AS ID, f1.RUTA, f1.EXTENSION, f1.FECHA AS FECHA, 0 AS TIPO, fe.FECHA AS FECHA_ORDEN
  11.                       FROM fotos_etiquetas fe, fotos f1
  12.                       WHERE fe.ID_A_QUIEN_ETIQUETA = $id_usuario AND f1.ID = fe.ID_FOTO) AS sbc, fotos_dimensiones fd
  13.                 WHERE sbc.ID != $id_img_usuario AND sbc.ID = fd.ID_FOTO AND fd.DIMENSIONES  = $tam
  14.                 ORDER BY sbc.FECHA_ORDEN DESC, sbc.TIPO ASC
  15.                 LIMIT 5


El tiempo de ejecucion es 0,0010 segs. Habrá que ver cuando hayan varios millones de filas :P


Esta es una captura de la explicacion que da, no me convence mucho por que veo muchas cosas nuevas. Pero puede que sea lo normal.

¿Como la veis vosotros?
  #7 (permalink)  
Antiguo 20/06/2011, 00:58
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 8 meses
Puntos: 574
Respuesta: Agupar por dos columnas, un poco diferente

JOIN aun que juega con el producto cartesiano lo hace de una manera contralada ya que se indica que campo relaciona las tablas.

En el producto cartesiano se aparean todos los registros de una tabla con todos los registros de la otra por el mero hecho de pertenecer a su tabla.

En un JOIN se aparean solo los registros que se relacionan por una condicion dada.

No te pongas a intentar eliminar todos los JOIN que tengas como se desprende de lo que dices... obviamente es una consulta mas cara, costosa, para el servidor pero es insustituible en muchos casos.

IN no permite el LIMIT!?!? No lo sabia.
__________________
Quim
--------------------------------------------------
Ayudar a ayudar es una buena práctica!!! Y da buenos resultados.
  #8 (permalink)  
Antiguo 20/06/2011, 07:07
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: Agupar por dos columnas, un poco diferente

Cita:
Al parecer, al usar UNION ALL, no se puede usar en cada una de las consultas el ORDER BY y el LIMIT. Se utilizaria el order by y el limit del final del SQL.
No si lo que quieres haer es un
Código MySQL:
Ver original 
Porque en ese contexto todos los SELECT componen en realidad una única consulta, y LIMIT sólo puede haber uno por consulta. lo que se peude hacer es transformar cada uno de ellos en una subconsulta:
Código MySQL:
Ver original
  1. SELECT * FROM (SELECT ... FROM .... LIMIT 1) T1
  2. SELECT * FROM (SELECT ... FROM .... LIMIT 1) T2
  3. SELECT * FROM (SELECT ... FROM .... LIMIT 1) T3
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Última edición por gnzsoloyo; 21/06/2011 a las 22:29
  #9 (permalink)  
Antiguo 21/06/2011, 19:55
 
Fecha de Ingreso: junio-2009
Mensajes: 309
Antigüedad: 15 años, 5 meses
Puntos: 5
Respuesta: Agupar por dos columnas, un poco diferente

Entiendo :D, muchas gracia spor la aclaracion!

Etiquetas: columnas, diferente, bases-de-datos
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 14:12.