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

1 consulta, 4 partes

Estas en el tema de 1 consulta, 4 partes en el foro de Mysql en Foros del Web. Estoy haciendo una web que tiene un foro y esta integrada con algunas bases de datos de un juego, el caso es que para mostrarlos ...
  #1 (permalink)  
Antiguo 19/06/2014, 18:27
Avatar de Macf  
Fecha de Ingreso: agosto-2007
Mensajes: 29
Antigüedad: 16 años, 7 meses
Puntos: 0
1 consulta, 4 partes

Estoy haciendo una web que tiene un foro y esta integrada con algunas bases de datos de un juego, el caso es que para mostrarlos en la pagina del perfil necesito recoger 4 datos distintos de 3 bases de datos: lastlogin (de la tabla authme), coins (de la tabla playerpoints), topics (temas iniciados en el foro, el nombre coincide con author_name y identificador tiene que ser 0 para que sea un tema y no una respuesta) y responses (respuestas en el foro, nombre = author_name y identificador!=0). Ahora viene lo divertido, lastlogin no tiene ningún problema, una consulta select tan simple como la que mas, pero que no puedo unir con la de coins (que es igual de simple) porque en la tabla de coins solo aparecen los usuarios que tienen coins, es decir, los que tienen el equivalente a 0 no aparecen, y cuando hago 1 sola query para las dos si coins no existe me devuelve null a todo, en lugar de solo a coins (para que me devolviera el lastlogin bien), luego el número de topics y de respuestas tambien es simple, un COUNT(*) en la misma tabla (foro) con unas clausulas where, pero no se hacer dos count en una misma query (y lo he buscado)

Estas son las 4 consultas que hago por separado:

Código SQL:
Ver original
  1. SELECT lastlogin FROM authme WHERE username= '$name'
  2. SELECT points AS coins  FROM playerpoints WHERE playername= '$name'
  3. SELECT COUNT(*) AS topics FROM foro WHERE author_name= '$name' AND identificador=0
  4. SELECT COUNT(*) AS responses FROM foro WHERE author_name= '$name' AND identificador!=0



Ya se que en el foro mysql no se puede poner codigo de cualquier otro lenguaje, pero por si a alguien le queda mas claro viendolo lo pongo, es el codigo php con el que me funciona bien el tinglado pero haciendolo en 4 consultas separadas, no pido ninguna ayuda con php ni siquiera un comentario sobre el, solo sobre las consultas sql, pero si aun así los moderadores lo quereis borrar no puedo hacer nada.
Cita:
Editado: Código de programación no permitido en foros de Bases de Datos.
Leer las normas del foro, por favor.
PD: Se que es obvio pero AUTHME_TABLE, MONEY_TABLE y FORUM_TABLE son constantes donde almaceno el nombre de las tablas, como pueden cambiar asi las cambio 1 vez en la config y no función por función

Un saludo, y gracias de antemano

Última edición por gnzsoloyo; 20/06/2014 a las 06:31
  #2 (permalink)  
Antiguo 19/06/2014, 20:26
Avatar de Patriarka  
Fecha de Ingreso: enero-2011
Ubicación: Moreno, Buenos Aires, Argentina
Mensajes: 2.851
Antigüedad: 13 años, 2 meses
Puntos: 288
Respuesta: 1 consulta, 4 partes

las db se encuentran en el mismo server?
cual es el problema de conectarte a varias db?
  #3 (permalink)  
Antiguo 20/06/2014, 04:49
Avatar de Macf  
Fecha de Ingreso: agosto-2007
Mensajes: 29
Antigüedad: 16 años, 7 meses
Puntos: 0
Respuesta: 1 consulta, 4 partes

Perdón, son 3 tablas distintas pero de la misma base de datos, ha sido un error mio de redacción. Tengo varios problemas, primero que como la segunda query, la de coins (tabla playerpoints) puede devolverme null, porque no existen registros de todos los usuarios, y eso me hace que la query entera me devuelva NULL si la uno con cualquiera de las otras, y mi segundo problema es que no se como unir las otras dos querys con COUNT en una sola query con las otras.
  #4 (permalink)  
Antiguo 20/06/2014, 06:35
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: 1 consulta, 4 partes

Cita:
la segunda query, la de coins (tabla playerpoints) puede devolverme null, porque no existen registros de todos los usuarios, y eso me hace que la query entera me devuelva NULL si la uno con cualquiera de las otras, y mi segundo problema es que no se como unir las otras dos querys con COUNT en una sola query con las otras.
El problema es básicamente que no puedes usar un simple JOIN y menos aún un JOIN implícito cuando tienes una relación opcional en una de las tablas de una query compuesta. Forzosamente debes usar JOINs explícitos (INNER, LEFT o RIGHT), y en especial LEFT JOIN.
El tema de los nulos en la relación se resuelve con funciones como IFNULL(), y COUNT() devolverá cero donde haya NULLs.
No se trata de una consulta compleja de hacer, pero es probable que haya que usar tablas derivadas (queries como tablas del FROM), para lograr eso, y que no se produzcan productos cartesianos.
__________________
¿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 20/06/2014, 12:30
Avatar de Macf  
Fecha de Ingreso: agosto-2007
Mensajes: 29
Antigüedad: 16 años, 7 meses
Puntos: 0
Respuesta: 1 consulta, 4 partes

Lo del IFNULL no parece para nada complicado cuando esté en casa lo implemento, pero los COUNTS con todas las cosas que me has dicho me has dejado digamos pasmado, yo eso no se hacerlo así que aun con pérdida de rendimiento si no hay algún alma caritativa que pierda 5min y me lo diga se va a quedar con 3 querys
  #6 (permalink)  
Antiguo 20/06/2014, 16:31
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: 1 consulta, 4 partes

Bueno, yo te tiro la idea de cómo la haría. Entender la lógica de la query te la dejo como tarea para la casa.
Código MySQL:
Ver original
  1. SELECT T1.lastlogin, T1.username, T1.coins, IFNULL(T2.topics, 0) topics, IFNULL(T2.responses, 0) responses
  2.     (SELECT A.lastlogin, A.username, IFNULL(PP.points, 0) coins
  3.     FROM authme A
  4.         LEFT JOIN playerpoints PP ON A.username= PP.playername
  5.     WHERE TRUE OR PP.playername IS NULL) T1
  6.     LEFT JOIN
  7.     (SELECT F.author_name, SUM(IF(F.identificador = 0, 1, 0)) topics, SUM(IF(F.identificador != 0, 1, 0)) responses
  8.     FROM foro F
  9.     GROUP BY F.author_name) T2 ON T1.username = T2.author_name
  10. WHERE TRUE OR T2.author_name IS NULL;

En cuanto al uso de LEFT JOIN, es algo que se puede ver en el manual de referencia (13.2.7.1. Sintaxis de JOIN, y 7.2.9. Cómo optimiza MySQL los LEFT JOIN y RIGHT JOIN), o bien en cualquier tutorial de MySQL, incluyendo algo que ya está en uno de los temas de ayuda de este mismo foro: Common MySQL Queries
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #7 (permalink)  
Antiguo 21/06/2014, 06:58
Avatar de Macf  
Fecha de Ingreso: agosto-2007
Mensajes: 29
Antigüedad: 16 años, 7 meses
Puntos: 0
Respuesta: 1 consulta, 4 partes

Muchisimas gracias gnzsoloyo, a ver si estudiando un poco entiendo como funciona hahaha
  #8 (permalink)  
Antiguo 22/06/2014, 09:07
Avatar de Macf  
Fecha de Ingreso: agosto-2007
Mensajes: 29
Antigüedad: 16 años, 7 meses
Puntos: 0
Respuesta: 1 consulta, 4 partes

Me da un poco de vergüenza, pero hoy que me he puesto a meter tu query en la web me ha surgido un problema, ¿donde le meto el nombre de usuario del que quiero averiguar los datos? seguro que soy yo que no lo veo pero me llevo tirando de los pelos un rato y ya no se que hacer.
  #9 (permalink)  
Antiguo 22/06/2014, 10:46
 
Fecha de Ingreso: diciembre-2005
Mensajes: 65
Antigüedad: 18 años, 4 meses
Puntos: 4
Respuesta: 1 consulta, 4 partes

Código MySQL:
Ver original
  1. SELECT A.lastlogin, A.username, IFNULL(PP.points, 0) coins
  2.     FROM authme A
  3.         LEFT JOIN playerpoints PP ON A.username= PP.playername
  4.     WHERE TRUE OR PP.playername IS NULL

Hay una cosa que no entiendo aquí y es el uso de
Código MySQL:
Ver original
  1. TRUE OR PP.playername IS NULL
  #10 (permalink)  
Antiguo 22/06/2014, 17:29
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: 1 consulta, 4 partes

Cita:
Iniciado por piwy Ver Mensaje
Código MySQL:
Ver original
  1. SELECT A.lastlogin, A.username, IFNULL(PP.points, 0) coins
  2.     FROM authme A
  3.         LEFT JOIN playerpoints PP ON A.username= PP.playername
  4.     WHERE TRUE OR PP.playername IS NULL

Hay una cosa que no entiendo aquí y es el uso de
Código MySQL:
Ver original
  1. TRUE OR PP.playername IS NULL
Es un caso estandar: Que devuelva todo (true no distingue), o que devuelva lo que no coincide en la segunda.
Mas o menos en todos los DBMS se usa de la misma forma cuando no tienes otras condiciones para el WHERE.
Si sólo pusieras
Código MySQL:
Ver original
  1. campo IS NULL
sólo devolvería lo que no coincide, excluyendo todo lo demás.
Y si no lo pones, podría actuar como un INNER JOIN, y excluir las no coincidentes.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #11 (permalink)  
Antiguo 23/06/2014, 04:01
Avatar de Macf  
Fecha de Ingreso: agosto-2007
Mensajes: 29
Antigüedad: 16 años, 7 meses
Puntos: 0
Respuesta: 1 consulta, 4 partes

Tengo un pequeño problema, ¿donde le meto el nombre de usuario del que quiero obtener los datos? no veo ningún sitio en la query para ello
  #12 (permalink)  
Antiguo 23/06/2014, 04: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: 16 años, 4 meses
Puntos: 2658
Respuesta: 1 consulta, 4 partes



Pues, como en cualquier consulta: En el WHERE...

Yo sólo te estoy dando un modelo estandar. Las condiciones adicionales (que no se habían mencionado antes), se las tienes que plantear tu.

Piénsalo de este modo: ¿Por qué pongo TRUE?
Pues porque no me dijiste qué otras condiciones debe cumplir la query.

Reemplaza el TRUE por lo que necesites...
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #13 (permalink)  
Antiguo 23/06/2014, 05:10
 
Fecha de Ingreso: diciembre-2005
Mensajes: 65
Antigüedad: 18 años, 4 meses
Puntos: 4
Respuesta: 1 consulta, 4 partes

Sí, te lo entiendo, lo que no te entiendo es:
Cita:
Y si no lo pones, podría actuar como un INNER JOIN, y excluir las no coincidentes.
Es un left join con poner el true es suficiente ¿?, el is null ¿no está de más?.
  #14 (permalink)  
Antiguo 23/06/2014, 05:42
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: 1 consulta, 4 partes

No es tan simple como eso. Hay algunos detalles que no vienen ahora al caso, y podrían cambia el comportamiento de MySQL. Lo que te propongo es un modelo de consulta que te funcione.
De la que te di, reemplaza el TRUE por la condición que quieres y conserva el NOT NULL.
Cuando hayas hecho la prueba (por tus preguntas estoy suponiendo que aún no lo hiciste), entonces veremos los detalles.
Haz la prueba.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #15 (permalink)  
Antiguo 23/06/2014, 08:08
 
Fecha de Ingreso: diciembre-2005
Mensajes: 65
Antigüedad: 18 años, 4 meses
Puntos: 4
Respuesta: 1 consulta, 4 partes

Hola gnzsoloyo, yo no soy el que formuló la pregunta inicial. Simplemente vi la respuesta que diste y me surgió la duda con el tema del left join y el is null que a mi me parece que no es necesario en este caso y por eso te preguntaba...

Etiquetas: null, partes, php, select, sql, tabla, usuarios
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 03:56.