Consulta dificil MYSQL

NeB1

Buenas a todos,

Necesito hacer una consulta, que me saque todas las "preguntas teoricas" (que es una tabla) que no están relacionadas con otra tabla (practicas operativas), y me saque: el idioma, dificultad, Y LA LISTA DE MODULOS SELECCIONADOS. Lo primero es relativamente sencillo, con una consulta tal como:

"SELECT t1.id, t1.pregunta AS Pregunta, t2.nombre AS Dificultad, t3.lenguaje AS Idioma
FROM preguntateorica AS t1, dificultadpt AS t2, idioma AS t3
WHERE t2.id=t1.idDificultadpt AND t3.id=t1.idIdioma AND t1.disponible='1' AND t1.id NOT IN

(
SELECT idPreguntaTeorica FROM preguntateoricapracticaoperativa WHERE idPracticaOperativa='".$_GET['id']."'
) GROUP BY t1.id"

Me lo saca sin problemas. El problema es sacar la lista de modulos formativos, que pueden ser muchos, asociados a la misma pregunta, me molaría poderlos sacar concatenados, algo así como:

"SELECT t1.id, t1.pregunta AS Pregunta, t2.nombre AS Dificultad, t3.lenguaje AS Idioma, CONCAT ( SELECT t4.nombre FROM moduloformativo AS t4, moduloformativopreguntateorica AS t5....)
FROM preguntateorica AS t1, dificultadpt AS t2, idioma AS t3
WHERE t2.id=t1.idDificultadpt AND t3.id=t1.idIdioma AND t1.disponible='1' AND t1.id NOT IN

(
SELECT idPreguntaTeorica FROM preguntateoricapracticaoperativa WHERE idPracticaOperativa='".$_REQUEST['id']."'

) GROUP BY t1.id"

Pero no consigo hacerlo que funcione. Es necesario que sea todo en una sola consulta, existe alguna forma?

NeB1

SIIIIIII con group_concat:

SELECT t1.id , t1.pregunta AS Pregunta , t2.nombre AS Dificultad, t3.lenguaje AS Idioma , GROUP_CONCAT( DISTINCT t4.nombre
SEPARATOR ', \n' ) AS Modulos
FROM preguntateorica AS t1, dificultadpt AS t2, idioma AS t3, moduloformativo AS t4, preguntateoricamoduloformativo AS t5
WHERE t4.id = t5.idModuloFormativo
AND t5.idPreguntaTeorica = t1.id
AND t2.id = t1.idDificultadpt
AND t3.id = t1.idIdioma
AND t1.disponible = '1'
AND t1.id NOT
IN (

SELECT idPreguntaTeorica
FROM preguntateoricapracticaoperativa
WHERE idPracticaOperativa = '23'
)
GROUP BY t1.id

bLaKnI

Ojito con GROUP_CONCAT!!!:

...
...
The result is truncated to the maximum length that is given by the group_concat_max_len system variable, which has a default value of 1024. The value can be set higher, although the effective maximum length of the return value is constrained by the value of max_allowed_packet. The syntax to change the value of group_concat_max_len at runtime is as follows, where val is an unsigned integer:
...

Sabes que significa?
Eso me ha traido dolores inmensos de cabeza para concatenados mediante group by grandes, donde IDs particulares crecen exponencialmente.
Te quedarás con cadenas cortadas y tendrás problemas!

NO CAMBIES EL VALOR POR DEFECTO DE LA VARIABLE EN UN INI!
Si prevées que tendrá la cadena mas de 1024 carácteres (comas incluídas), haz 2 queries, y luego con un doble for anidado, dedícate a generar cadenas separándolas tu manualmente mediante comas, por ejemplo.

Tenlo en cuenta, que esto en mi trabajo nos ha obligado a ir query por query en donde se usara el GROUP_CONCAT y revisando cuales podian "petar".

Saludos! ;)

NeB1

#3 bueeeenaaaaa, en principio no preveo que vaya a pasar los 1024 carácteres. La cuestión es que estoy gastando una API cuyo principal problema es que me limita a una única sentencia SQL para sacarlo todo.

Y no tendría problema en modificar la API yo mismo, ya que está escrita en PHP, pero es que está super ofuscada, yo no he conseguido sacar el código fuente ni lo más mínimo.

Gracias por el aviso, me ahorro futuros dolores de cabeza ^.

Pd1:Si paso de 1024 carácteres, se para la cadena en el último caracter o peta la query?

Pd2:group_concat_max_len at runtime is as follows, where val is an unsigned integer:
... Te ha faltado acabar esa frase xDD así lo preparo antes de cada sentenica :P

bLaKnI

Queda la cadena cortada.
Es decir, no peta. Te devuelva "hasta 1024". :)

edit:

SET [GLOBAL | SESSION] group_concat_max_len = val;

http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

En PHP deberias ver como se inicializan las variables al principio, que no me acuerdo. Mirate la API de PHP.net en la sección de MySQL que fijo que lo explica :)

NeB1

#5 por lo que pone en la docu que me has pasado, debería valer metiendo al inicio de la consulta algo así como:

SET SESSION group_concat_max_len = 16384;

y despues tirar el resto de la consulta. De todos modos, me vale con que no se pete la consulta de momento, hasta que no vea algún caso especial, o hasta que no me hagan hacer lo que creo que van a querer que les haga algún día.

Usuarios habituales

  • NeB1
  • bLaKnI