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

[SOLUCIONADO] No se formular la sentencia mysql

Estas en el tema de No se formular la sentencia mysql en el foro de Bases de Datos General en Foros del Web. Buenas, Llevo rato peleándome con una sentencia mysql y no sé si me estoy liando, si estoy ofuscada, .... la cuestión es que no me ...
  #1 (permalink)  
Antiguo 29/05/2016, 13:56
 
Fecha de Ingreso: enero-2002
Ubicación: Sabadell
Mensajes: 565
Antigüedad: 22 años, 3 meses
Puntos: 4
No se formular la sentencia mysql

Buenas,
Llevo rato peleándome con una sentencia mysql y no sé si me estoy liando, si estoy ofuscada, .... la cuestión es que no me sale. Si alguien puede ayudarme, muy agracedida

Tengo dos tablas, 'tasques':


subtasques:


Lo que pretendo es visualizar todas las tascas con el estado de la última subtasca, para ello, la sentencia que ejecuto es esta:

Código MySQL:
Ver original
  1. SELECT * FROM tasques as t
  2. LEFT JOIN clients AS c ON (t.idclient = c.id)
  3.     (SELECT s.idtasca, s.idestat, s.datavenciment FROM subtasques AS s
  4.         ORDER BY s.idtasca, datarecepcio DESC
  5.     )
  6. AS s ON (t.id = s.idtasca)
  7. LEFT JOIN estat AS e ON (s.idestat = e.id)
  8. ORDER BY client

Deberían salir sólo los marcados en amarillo y salen todos:



Gracias
__________________
Qué fácil cuando lo sabes y qué difícil cuando no
  #2 (permalink)  
Antiguo 30/05/2016, 07:40
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 17 años, 8 meses
Puntos: 774
Respuesta: No se formular la sentencia mysql

y las demas tablas? en esa consulta usas 4 tablas y nada mas muestras datos de 2
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me
  #3 (permalink)  
Antiguo 30/05/2016, 07:59
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: No se formular la sentencia mysql

Como te dice Libras, estás mostrando sólo datos de dos de las tabas, pero tu JOIN está devolviendo los registros de cuatro de ellas.
El problema es que cuando recorres el set de resultado, puedes estar tomando registros que repiten datos, porque los datos que las diferencian son de las dos tablas cuyas columnas NO muestras.
Es imposible saberlo con certeza, porque tu consulta tiene el clasico caso de obtener TODAS las columnas, incluso las superfluas... SELECT * es la peor forma de consulta para ser usada en reportes. Sería preferible que usaras un SELECT acotado a las columnas que realmente necesitas.
Además, estás creando una relación en estrella, lo que puede dar resultados imprevisibles, dado que relacionas la primera tabla con la segunda, pero la tercera (la subquery) la relacionas con la primera, sin vinculo con la segunda, lo que podría dar resultados inesperados o inválidos.

Hay que tener MUCHO cuidado cuando se usa exclusivamente LEFT JOIN. Para que los datos sean consistentes el LEFT JOIN debe relacionar sólo los datos entre la tabla izquierda y la derecha del JOIN, sin saltarse ninguna. ¿se entiende?.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #4 (permalink)  
Antiguo 30/05/2016, 11:56
 
Fecha de Ingreso: enero-2002
Ubicación: Sabadell
Mensajes: 565
Antigüedad: 22 años, 3 meses
Puntos: 4
Respuesta: No se formular la sentencia mysql

Gracias a ambos por responder.
Uso SELECT * porqué la tabla tiene 3 campos y quiero los 3.

Es verdad, me he olvidado de poner las otras dos tablas.

clients:


estat:


Soy consciente de que lo estoy haciendo mal, pero no me sale.

Gracias
__________________
Qué fácil cuando lo sabes y qué difícil cuando no
  #5 (permalink)  
Antiguo 30/05/2016, 12:09
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 17 años, 8 meses
Puntos: 774
Respuesta: No se formular la sentencia mysql

Lo que pasa es que tu tabla subtasques(que es una tasque??? me suena como a un animal mitologico jejejeje terrasque) tienes mas de una entrada para cada tasque, lo que ocasiona que la informacion se presente "duplicada" aqui lo que debes de hacer es nada mas obtener el registro que te interesa para esto revisando tus datos es el que tiene la fecha maxima de vencimiento, esto es correcto? de ser asi tu query quedaria parecido a esto:



Código SQL:
Ver original
  1. SELECT * FROM tasques AS t
  2. LEFT JOIN clients AS c ON (t.idclient = c.id)
  3. LEFT JOIN
  4.     (SELECT s.idtasca, s.idestat, s.datavenciment FROM subtasques AS s
  5. LEFT JOIN(SELECT MAX(datavencimient) AS datavenciment, idtasca FROM subtasques GROUP BY idtasca) AS r ON (s.idtasca=r.idtasca AND s.datavenciment =r.datavenciment  )
  6.         ORDER BY s.idtasca, s.datarecepcio DESC
  7.     )
  8. AS s ON (t.id = s.idtasca)
  9. LEFT JOIN estat AS e ON (s.idestat = e.id)
  10. ORDER BY client
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me

Última edición por Libras; 30/05/2016 a las 12:15
  #6 (permalink)  
Antiguo 30/05/2016, 14:57
 
Fecha de Ingreso: enero-2002
Ubicación: Sabadell
Mensajes: 565
Antigüedad: 22 años, 3 meses
Puntos: 4
Respuesta: No se formular la sentencia mysql

Gracias Libras, nada que ver con un animal mitológico tasques = tareas en catalán. A menudo lo traduzco para postear, pero es fácil equivocarse con una letra y luego es un lío.

Has entendido lo que quiero, pero la sentencia que me has propuesto devuelve, exactamente, los mismos registros que la mía.
__________________
Qué fácil cuando lo sabes y qué difícil cuando no
  #7 (permalink)  
Antiguo 30/05/2016, 15:25
Avatar de Libras
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: En la hermosa perla de occidente
Mensajes: 7.412
Antigüedad: 17 años, 8 meses
Puntos: 774
Respuesta: No se formular la sentencia mysql

La verdad no revise los datos, pero esa es mas o menos la idea, ahora trabaja un poquito para obtener lo que necesitas :)
__________________
What does an execution plan say to t-sql query? Go f**k yourself, if you are not happy with me
  #8 (permalink)  
Antiguo 30/05/2016, 15:31
 
Fecha de Ingreso: enero-2002
Ubicación: Sabadell
Mensajes: 565
Antigüedad: 22 años, 3 meses
Puntos: 4
Respuesta: No se formular la sentencia mysql

Lo he revertido, y parece funcionar. Gracias

Código MySQL:
Ver original
  1. SELECT MAX(s.datavenciment), c.client, t.concepte, e.estat, e.color FROM subtasques AS s
  2. LEFT JOIN tasques AS t ON (s.idtasca = t.id)
  3. LEFT JOIN clients AS c ON (t.idclient = c.id)
  4. LEFT JOIN estat AS e ON (s.idestat = e.id)
  5. GROUP BY s.idtasca DESC
  6. ORDER BY c.client
__________________
Qué fácil cuando lo sabes y qué difícil cuando no

Última edición por mblascog; 30/05/2016 a las 16:00
  #9 (permalink)  
Antiguo 31/05/2016, 04:25
 
Fecha de Ingreso: enero-2002
Ubicación: Sabadell
Mensajes: 565
Antigüedad: 22 años, 3 meses
Puntos: 4
Respuesta: No se formular la sentencia mysql

Lo he estado probando y tampoco funciona. Se mezclan los registros, visualiza la fecha de vencimiento más reciente, pero estat no se corresponde.
__________________
Qué fácil cuando lo sabes y qué difícil cuando no
  #10 (permalink)  
Antiguo 31/05/2016, 05:46
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: No se formular la sentencia mysql

No prestaste mucha atención a lo que te menciono, no?

Cita:
Además, estás creando una relación en estrella, lo que puede dar resultados imprevisibles, dado que relacionas la primera tabla con la segunda, pero la tercera (la subquery) la relacionas con la primera, sin vinculo con la segunda, lo que podría dar resultados inesperados o inválidos.

Hay que tener MUCHO cuidado cuando se usa exclusivamente LEFT JOIN. Para que los datos sean consistentes el LEFT JOIN debe relacionar sólo los datos entre la tabla izquierda y la derecha del JOIN, sin saltarse ninguna.
Por empezar, veamos si se puede diseñar mejor esa consulta, para lo cual hay una pregunta básica: ¿Pueden existir tareas sin clientes?
La segunda es: ¿Pueden existir tareas sin estados?

Si la respuesta a ambas preguntas es NO, entonces la consulta está MAL planteada en sus JOIN.
Si la respuesta a la primera es SI y a la segunda, NO, el segundo JOIN está MAL.
Si la respuesta a la primera es NO y a la segunda SI, el primer JOIN está MAL.
Y si la respuesta a ambas es SI, entonces la lógica de la query está MAL planteada y necesita hacerse con otra estrategia.

¿Cual es la respuesta?
__________________
¿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 31/05/2016, 06:13
 
Fecha de Ingreso: enero-2002
Ubicación: Sabadell
Mensajes: 565
Antigüedad: 22 años, 3 meses
Puntos: 4
Respuesta: No se formular la sentencia mysql

Te prometo gnzsoloyo, por la cuenta que me trae, que presto muchísima atención a vuestros comentarios, aúnque quizás no los sepa interpretar.

- no pueden existir tareas sin clientes
- no pueden existir tareas sin subtareas
- no pueden existir subtareas sin estado

Gracias
__________________
Qué fácil cuando lo sabes y qué difícil cuando no
  #12 (permalink)  
Antiguo 31/05/2016, 07:13
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: No se formular la sentencia mysql

Pues si la respuesta es NO, entonces no procede usar LEFT JOIN.

Empecemos probando esto:
Código SQL:
Ver original
  1. SELECT c.idclient, c.client, t.historic, c.directori, t.id idtasca, e.idestat, s.datavenciment, e.estat, e.color
  2. FROM clients c
  3.         INNER JOIN tasques t ON t.idclient = c.id
  4.         INNER JOIN subtasques s ON t.id = s.idtasca
  5.         INNER JOIN  estat e ON s.idestat = e.id
  6. ORDER BY c.client, t.id ;

Consejo: No uses "ID" como nombre de columna Usalos siempre con un nombre con prefijo o sufijo que lo identifique, incluso en su propia tabla.
Facilita la escritura de las consultas.
__________________
¿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 31/05/2016, 09:49
 
Fecha de Ingreso: enero-2002
Ubicación: Sabadell
Mensajes: 565
Antigüedad: 22 años, 3 meses
Puntos: 4
Respuesta: No se formular la sentencia mysql

Gracias, pero sigo con el mismo problema. La sentencia sql que has escrito devuelve este resultado



Y lo que busco es que solo visualize un registro por tasca, el que contenga la fecha vencimiento más reciente, y es lo que no consigo y dónde realmente me lío

Es decir, el resultado esperado es el siguiente:




Si modifico la sentencia sql así

Código MySQL:
Ver original
  1. SELECT c.id, c.client, t.historic, c.directori, t.id idtasca, e.id, venciment, e.estat, e.color
  2. FROM clients c
  3.         INNER JOIN tasques t ON t.idclient = c.id
  4.         INNER JOIN (SELECT MAX(datavenciment) AS venciment, idtasca, idestat FROM subtasques GROUP BY idtasca) AS s ON t.id = s.idtasca
  5.         INNER JOIN  estat e ON s.idestat = e.id
  6. ORDER BY c.client, t.id;

El número de registros es correcto, pero el estado no se corresponde

__________________
Qué fácil cuando lo sabes y qué difícil cuando no

Última edición por mblascog; 31/05/2016 a las 10:10
  #14 (permalink)  
Antiguo 31/05/2016, 10:12
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: No se formular la sentencia mysql

Como te dije, era para PROBAR, no para tener la solucion.
La idea es que yo entendiese lo que quieres.

Prueba esto:
Código MySQL:
Ver original
  1. SELECT  idclient,  client,  historic,  directori,  idtasca,  idestat,  datavenciment,  estat,  color
  2.     (SELECT
  3.         c.idclient,
  4.         c.client,
  5.         t.historic,
  6.         c.directori,
  7.         t.id idtasca,
  8.         e.idestat,
  9.         s.datavenciment,
  10.         e.estat,
  11.         e.color
  12.     FROM clients c
  13.             INNER JOIN tasques t ON t.idclient = c.id
  14.             INNER JOIN subtasques s ON t.id = s.idtasca
  15.             INNER JOIN  estat e ON s.idestat = e.id
  16.     ORDER BY c.client ASC, s.datavenciment DESC) t1
  17. GROUP BY client ;

Atención, esta es una solución exclusivamente para MySQL. No la puedes usar en otros DBMS porque te dispararía un error.
__________________
¿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 31/05/2016, 10:30
 
Fecha de Ingreso: enero-2002
Ubicación: Sabadell
Mensajes: 565
Antigüedad: 22 años, 3 meses
Puntos: 4
Respuesta: No se formular la sentencia mysql

Gracias por tu colaboración gnzsoloyo.


Con tu sentencia anterior obtuve el número de registros correctos per el estado era incorrecto



Con esta última sentencia, los registros que salen son correctos, pero faltan



Client1 y Didac tienen 2 subtareas y ahora sólo sale una
__________________
Qué fácil cuando lo sabes y qué difícil cuando no
  #16 (permalink)  
Antiguo 31/05/2016, 11:22
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: No se formular la sentencia mysql

Ajustemos, entonces. para lograrlo hay que ordenar por cliente, tarea, subtarea y fecha, esta última en orden descendente

Código MySQL:
Ver original
  1. SELECT  idclient,  client,  historic,  directori,  idtasca,  idestat,  datavenciment,  estat,  color
  2.     (SELECT
  3.         c.idclient,
  4.         c.client,
  5.         t.historic,
  6.         c.directori,
  7.         t.id idtasca,
  8.         e.idestat,
  9.         s.datavenciment,
  10.         e.estat,
  11.         e.color
  12.     FROM clients c
  13.             INNER JOIN tasques t ON t.idclient = c.id
  14.             INNER JOIN subtasques s ON t.id = s.idtasca
  15.             INNER JOIN  estat e ON s.idestat = e.id
  16.     ORDER BY c.client ASC, t.id DESC, s.datavenciment DESC) t1
  17. GROUP BY client, idtasca;

Ten en cuenta que estoy haciendo las propuestas en forma teórica. Si hay cambios menores que puedan realizarse para ajustar el resultado, los tienes que intentar tu. Yo NO tengo tu base ni tus datos para hacer preubas.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #17 (permalink)  
Antiguo 31/05/2016, 13:42
 
Fecha de Ingreso: enero-2002
Ubicación: Sabadell
Mensajes: 565
Antigüedad: 22 años, 3 meses
Puntos: 4
Respuesta: No se formular la sentencia mysql

Gracias gnzsoloyo, casi dos días luchando por esto. Al final tu me lo has resuelto. Muchas gracias
__________________
Qué fácil cuando lo sabes y qué difícil cuando no
  #18 (permalink)  
Antiguo 01/06/2016, 06:54
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: No se formular la sentencia mysql



__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Etiquetas: mysql
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 21:09.