Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   consulta sql compleja (https://www.clubdelphi.com/foros/showthread.php?t=93976)

jsc 03-06-2019 11:27:21

consulta sql compleja
 
Hola,
quisiera pediros ayuda en una consulta sql que no consigo resolver y que no se si podria ejecutarse
tengo tres tablas

[tbl_PREGUNTAS]
idPREG
PREGUNTA
idRESPok

[tbl_RESPUESTAS]
idRESP
idPREG
OPCION

[tbl_testCOMPLETADO]
idTEST
idPREG
miRespuesta

La cuestion es que estoy intentando ejecutar una consulta, donde me de como resultado, las preguntas mal respondidas de un test en cuestion, mostrandome a su vez, la opcion correcta y la opcion incorrecta que yo marque en el test

En el programa, muestro un test de N preguntas con sus correspondientes respuestas (4 opciones) y para cada pregunta, el usuario selecciona la respuesta que almaceno como miRespuesta en tbl_TESES

A su vez, previamente hemos marcado en la base de datos, la respuesta correcta a cada pregunta a traves del campo idRESPok en la tabla tbl_PREGUNTAS

Poniendo un ejemplo,

tbl_PREGUNTAS

idPREG - PREGUNTA - idRESPok
-----------------------------------------------------
1 - Preg 1 - 3
2 - Preg 2 - 5
3 - Preg 3 - 10

tbl_RESPUESTAS

idRESP - idPREG - OPCION
-----------------------------------------------------
1 - 1 - a:Respuesta a, preg 1
2 - 1 - b:Respuesta b, preg 1
3 - 1 - c:Respuesta c, preg 1
4 - 1 - d:Respuesta d, preg 1
5 - 2 - a:Respuesta a, preg 2
6 - 2 - b:Respuesta b, preg 2
7 - 2 - c:Respuesta c, preg 2
8 - 2 - d:Respuesta d, preg 2
9 - 3 - a:Respuesta a, preg 3
10 - 3 - b:Respuesta b, preg 3
11 - 3 - c:Respuesta c, preg 3
12 - 3 - d:Respuesta d, preg 3

tbl_testCOMPLETADO

idTEST - idPREG - miRespuesta
---------------------------------------------------------
1 - 1 - 2
1 - 2 - 6
1 - 3 - 10

El resultado que quisiera obtener seria (preguntas mal respondidas de un test con la opcion correcta e incorrecta):

PREGUNTA OPCION(Bien) OPCION(Mal)
------------------------------------------------------------------------
Preg 1 c:Respuesta c, preg 1 b:Respuesta b, preg 1
Preg 2 a:Respuesta a, preg 2 b:Respuesta b, preg 2

Nota: la pregunta 3 no se mostraria, porque en el test marcamos la opcion correcta

Consigo sacar sin problemas las respuestas mal respondidas, mostrando la opcion correcta, pero me es imposible añadir el campo opcion incorrecta

Consulta que me funciona para mostrar solo la opcion correcta

Código SQL [-]
PARAMETERS pIDTest Text ( 255 );
SELECT PREGUNTAS.PREGUNTA, RESPUESTAS.OPCION, PREGUNTAS.idRESPOK, tbl_testCOMPLETADO.miRespuesta, RESPUESTAS.idRESP

FROM (PREGUNTAS INNER JOIN tbl_testCOMPLETADO ON PREGUNTAS.idPREG = tbl_testCOMPLETADO.idPREG) INNER JOIN RESPUESTAS ON PREGUNTAS.idPREG = RESPUESTAS.idPREG

WHERE (((tbl_testCOMPLETADO.miRespuesta)<>[PREGUNTAS].[idRESPOK]) AND ((RESPUESTAS.idRESP)=Nz([PREGUNTAS].[idRespOK],0)) AND ((tbl_testCOMPLETADO.idTest)=[pIDTest]));

Consulta que intento obtener sin exito para mostrar opcion incorrecta

Código SQL [-]
PARAMETERS pIDTest Text ( 255 );
SELECT PREGUNTAS.PREGUNTA, RESPUESTAS.OPCION AS Correcta, PREGUNTAS.idRESPOK, tbl_testCOMPLETADO.miRespuesta, RESPUESTAS.idRESP, malResp.Incorrecta

FROM ((PREGUNTAS INNER JOIN tbl_testCOMPLETADO ON PREGUNTAS.idPREG = tbl_testCOMPLETADO.idPREG) INNER JOIN RESPUESTAS ON PREGUNTAS.idPREG = RESPUESTAS.idPREG),

(SELECT RESPUESTAS.OPCION AS Incorrecta 
FROM (RESPUESTAS INNER JOIN tbl_testCOMPLETADO ON RESPUESTAS.idPREG=tbl_testCOMPLETADO.idPREG) inner join preguntas on preguntas.idpreg =respuestas.idpreg
WHERE preguntas.idrespok <> tbl_testcompletado.miRespuesta AND tbl_testCOMPLETADO.idTEST = [pIDTest] AND RESPUESTAS.idRESP = tbl_testCOMPLETADO.miRespuesta)  AS malResp

WHERE (((tbl_testCOMPLETADO.miRespuesta)<>[PREGUNTAS].[idRESPOK]) AND ((RESPUESTAS.idRESP)=Nz([PREGUNTAS].[idRespOK],0)) AND ((tbl_testCOMPLETADO.idTest)=[pIDTest]))

Con esto, el resultado que obtengo es por ejemplo:

PREGUNTA OPCION(Bien) OPCION(Mal)
-------------------------------------------------------------------
Preg 1 c: Respuesta c, Preg 1 b:Respuesta b, preg 1
Preg 1 c: Respuesta c, Preg 1 b:Respuesta b, preg 2

Preg 2 a:Respuesta a, preg 2 b:Respuesta b, preg 1
Preg 2 a:Respuesta a, preg 2 b:Respuesta b, preg 1

Espero haberme explicado,
Agradezco vuestra ayuda de antemano

juniorSoft 03-06-2019 17:21:08

Si es Sql Server aunque lo estoy escribiendo aquí sin probarlo en el entorno debe andar por ahí

Código SQL [-]
select P.pregunta, R.opcion, TC.miRespuesta, (case  when R.opcion = TC.miRespuesta then 'Correcta' else 'Incorrecta')as Resultado  from tbl_PREGUNTAS P inner join tbl_RESPUESTAS R on (P.idpreg = R.idPreg)
inner join tbl_testCOMPLETADO TC on (P.idPreg = TC.idPreg)
where .... --la condicion del test  que se este evaluando

jsc 03-06-2019 17:37:02

Hola,
Gracias por la respuesta

El entorno no es SQL Server, sino Access
Probare lo que me comentas, buscando el equivalente a select case en access que por lo que he encontrado podria hacerse con IIF(a evaluar,valor verdadero,valor falso)

Me has dado una buena pista

Muchas gracias
Comentare el progreso

juniorSoft 03-06-2019 18:00:04

^\||/^\||/, también si fuera sql server en el case falto el end que termina la instrucción case

jsc 04-06-2019 01:50:10

1 Archivos Adjunto(s)
Cita:

Empezado por juniorSoft (Mensaje 532276)
Si es Sql Server aunque lo estoy escribiendo aquí sin probarlo en el entorno debe andar por ahí

Código SQL [-]
select P.pregunta, R.opcion, TC.miRespuesta, (case  when R.opcion = TC.miRespuesta then 'Correcta' else 'Incorrecta')as Resultado from tbl_PREGUNTAS P inner join tbl_RESPUESTAS R on (P.idpreg = R.idPreg)
inner join tbl_testCOMPLETADO TC on (P.idPreg = TC.idPreg)
where .... --la condicion del test  que se este evaluando

hola, como dije, gracias de antemano por tu aporte
trabajo sobre access 2010

probe lo que me comentas, pero no obtengo el resultado que quiero
no me interesa mostrar con un [TEXT] indicando si la respuesta esta bien o mal respondida que entiendo es lo que evalua
Código SQL [-]
(case  when R.opcion = TC.miRespuesta then 'Correcta' else 'Incorrecta')as Resultado

lo que quiero es, mostrar las preguntas que se han respondido mal y mostrar el campo [OPCION] con su respuesta correcta y su respuesta incorrecta

pongo otro ejemplo por si pudiera verse mas claro adjuntando un pdf
como dije antes, lo que llego a conseguir es sacar los datos que quiero, exceptuando la columna que se ve en la imagen como [miRespuesta: INCORRECTA]

la consulta que ejecuto es esta (faltaria añadir lo que no consigo, la columna con la opcion INCORRECTA y para la que os pido ayuda)

Código SQL [-]
PARAMETERS pIDTest Text ( 255 );
SELECT PREGUNTAS.PREGUNTA, RESPUESTAS.OPCION AS Correcta, PREGUNTAS.idRESPOK, tbl_testCOMPLETADO.miRespuesta, RESPUESTAS.idRESP

FROM (PREGUNTAS INNER JOIN tbl_testCOMPLETADO ON PREGUNTAS.idPREG = tbl_testCOMPLETADO.idPREG) INNER JOIN RESPUESTAS ON PREGUNTAS.idPREG = RESPUESTAS.idPREG

WHERE (((tbl_testCOMPLETADO.miRespuesta)<>[PREGUNTAS].[idRESPOK]) AND ((RESPUESTAS.idRESP)=Nz([PREGUNTAS].[idRespOK],0)) AND ((tbl_testCOMPLETADO.idTest)=[pIDTest]))

Saludos y gracias por vuestro tiempo y ayuda

juniorSoft 04-06-2019 04:18:14

por lo que veo entonces es algo con las condiciones en el where o las condiciones de los Joins

En esta condición filtras las respuestas incorrectas

Código SQL [-]
(((tbl_testCOMPLETADO.miRespuesta)<>[PREGUNTAS].[idRESPOK])

En la siguiente condición teniendo la primera condición quieres igualar una respuesta correcta con las preguntas que ya se filtraron como incorrectas
Código SQL [-]
AND ((RESPUESTAS.idRESP)=Nz([PREGUNTAS].[idRespOK],0))

y si ademas estas condiciones se contradicen con las condiciones de la unión de las tablas puede que no obtengas los resultados que esperas

Lo que te propongo es que depures esa consulta utilizando aquel refrán que dice "Divide y Vencerás".

Has la consulta básica de las preguntas incorrectas si te sale bien, sigue agregando y probando las demás condiciones hasta que encuentres donde esta el problema. Si tienes condiciones excluyentes y cada condición devuelve un conjunto de resultados que te interesa quizás necesites hacer un union. Hacer un select con las primeras condiciones luego union y luego el otro select con las otras condiciones, los campos de ambos select deben coincidir.

jsc 05-06-2019 01:33:33

Mostrando el valor del campo de una tabla con DOS posibles valores en DOS columnas
 
Hola otra vez,

Gracias juniorSoft por haber dedicado parte de tu tiempo...

Hasta las pruebas que he llegado hacer, parece que he ENCONTRADO LA SOLUCION

Buscando, buscando pense que podrian ir los tiros por aqui (ejemplo sacado de: http://www.forosdelweb.com/f86/recup...-tabla-697316/

Una consulta sobre una tabla a la que se ejecuta un JOIN sobre si misma

Código SQL [-]
SELECT alumnos.nif, alumnos.nombre, t1.total totalpendientes
  FROM alumnos INNER JOIN
    (SELECT alumno, COUNT(*) total FROM examenes
      WHERE evaluado = FALSE GROUP BY alumno HAVING total >=1 )t1
         ON alumnos.nif = t1.alumno ORDER BY alumnos.nombre


La cuestion es que, tambien encontre este otro ejemplo en el que me he basado y he conseguido al parecer que funcione para mis objetivos: http://www.forosdelweb.com/f86/dos-c...r-sql-1047898/

Muestra dos columnas con valores diferentes para un mismo campo de una misma tabla

Código SQL [-]
SELECT reparaciones.id, F1.descripcion falla_representante, F2.descripcion falla_tecnicor
FROM reparaciones R 
    INNER JOIN falla F1 on R.falla_representante_ID_falla = F1.ID 
    INNER JOIN falla F2 on R.falla_tecnico_ID_falla = F2.ID

Aplicando digamos los dos ejemplos, la consulta me quedo de la siguiente manera
Por si alguien podria serle de utilidad...

Código SQL [-]
SELECT tblTC.PREGUNTA, RBIEN.OPCION, RMI.OPCION

FROM 

((SELECT RB.OPCION,RB.IDPREG,PB.IDRESPOK FROM (tbl_testCOMPLETADO AS TC INNER JOIN PREGUNTAS AS PB ON TC.idPREG = PB.idPREG) INNER JOIN RESPUESTAS AS RB ON PB.idPREG = RB.idPREG
WHERE tc.idtest=pidtest and rB.idresp=pB.idrespok and tc.miRespuesta <> pb.idrespok GROUP BY RB.OPCION,RB.IDPREG,PB.IDRESPOK)  AS RBIEN INNER JOIN

(SELECT RA.OPCION,RA.IDPREG,PA.IDRESPOK FROM (tbl_testCOMPLETADO AS TC INNER JOIN PREGUNTAS AS PA ON TC.idPREG = PA.idPREG) INNER JOIN RESPUESTAS AS RA ON PA.idPREG = RA.idPREG
WHERE TC.idtest=[pidtest] AND RA.idresp=tc.mirespuesta and tc.miRespuesta<>pa.idrespok GROUP BY RA.OPCION,RA.IDPREG,PA.IDRESPOK)  AS RMI ON RBIEN.IDPREG = RMI.IDPREG) INNER JOIN

tbl_testCOMPLETADO AS tblTC ON RMI.IDPREG = tblTC.IDPREG

GROUP BY tblTC.PREGUNTA, RBIEN.OPCION, RMI.OPCION;


En definitiva, pongo un resumen a groso modo de en lo que consistiria la consulta

Código SQL [-]
SELECT de tblP.Pregunta, RespBien.opcion, MiResp.opcion

FROM (
(select campos from tablaA inner join tablaB) inner join tablaC WHERE condiciones para OPCION CORRECTA GROUP BY campos) as RespBien
INNER JOIN
(select campos from tablaA inner join tablaB) inner join tablaC WHERE condiciones para LA OPCION QUE MARCO EL USUARIO(miRespuesta) GROUP BY campos) as MiResp )
INNER JOIN
tblP

GROUP BY tblP.Pregunta, RespBien.opcion, MiResp.opcion

juniorSoft 05-06-2019 03:43:19

Cita:

Muestra dos columnas con valores diferentes para un mismo campo de una misma tabla
Si también es posible utilizar una misma tabla con diferentes alias.


Veo que haces muchos sub-select, quizas con sql server hace un plan de ejecución pero no se que tan eficiente sea esa consulta en MS-access, quizás puedas hacer pruebas introduciendo muchos registros en esas tablas a ver como responde

bucanero 05-06-2019 10:05:45

hola a todos

mira si te puede servir esta consulta:
Código SQL [-]
  SELECT test.idTest,
       test.idpreg,
       pre.PREGUNTA,
       idRESPOK,
       resCorrectas.OPCION AS RespuestaCorrecta,
       miRespuesta,
       resUser.Opcion AS RespuestaUsuario
  FROM (-- test con todas las preguntas
        tbl_testCompletado test
        INNER JOIN tbl_PREGUNTAS pre ON test.idpreg = pre.idpreg)
       -- respuestas correctas
       INNER JOIN tbl_RESPUESTAS resCorrectas ON resCorrectas.idRESP = idRESPOK
       -- respuestas del usuario
       INNER JOIN tbl_RESPUESTAS resUser ON resUser.idRESP = miRespuesta
 WHERE test.idTEst = 1
-- Activar esta opcion para mostrar solo las respuestas incorrectas
-- and idRESPOK <> miRespuesta


La franja horaria es GMT +2. Ahora son las 10:54:37.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi