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

no hace caso a condición

Estas en el tema de no hace caso a condición en el foro de Mysql en Foros del Web. Hola a todos, es mi primer post en este subforo, espero que me puedan ayudar. Acerca de esta consulta: Código PHP: SELECT D . nick , ...
  #1 (permalink)  
Antiguo 26/06/2010, 14:39
 
Fecha de Ingreso: marzo-2008
Mensajes: 100
Antigüedad: 16 años, 1 mes
Puntos: 0
no hace caso a condición

Hola a todos, es mi primer post en este subforo, espero que me puedan ayudar.
Acerca de esta consulta:
Código PHP:
SELECT D.nick,SUM(D.points)AS points,
 
COUNT((SELECT COUNT(*) FROM misiones M WHERE M.mn D.mn AND M.ot 'Official 2' GROUP BY M.mn)) 'of2',
 
COUNT((SELECT COUNT(*) FROM misiones M WHERE M.mn D.mn  AND D.task='Partial' GROUP BY M.mn)) 'ofsucces'
FROM disparos D GROUP BY D.nick 
por qué no escucha la condición D.task='Partial' ?

Dentro del COUNT, cualquier condición que le ponga acerca de la tabla misiones M, me la escucha, pero cuando le pongo una condición de la tabla disparos D no,

El caso es que no me da error, y me ejecuta la consulta dando el resultado como si la condición D.task='Partial' no estuviera.

Alguienb sabe por qué puede ser? o alguien sabe como podría plantear la consulta para que me atendiera a esa condicón?

Gracias!!
  #2 (permalink)  
Antiguo 26/06/2010, 14: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 hace caso a condición

A mi entender, puede que estés complicando demasiado la consulta, y no se ven ciertos detalles del comportamiento de la consulta:
Cuanco pones una subconsulta como salida de una columna del SELECT, esta consulta se compara con cada uno de los resultados de la consulta principal, siendo que no en todos los casos el WHERE de la subconsulta dará TRUE.
Además, el GROUP BY de la consulta mayor no parece coincidir con las subconsultas (al menos no es el mismo campo), lo que puede dar lugar a que las sumatorias que realmente se estén produciendo queden ocultas en el agrupamiento, por cuanto en este caso sólo conservará el primer registro de cada grupo de "nick" encontrado... que puede no coincidir en el "mn" de la subconsulta, lo que devolvería cero (0) en esos casos.
Además de esas dos cosas, la consulta se vuelve innecesariamente ineficiente, ya que realiza cada subconsulta, al menos una vez por nick encontrado... en lugar de hacerlo una sola vez para todos los nicks, cosa que sería mucho mejor.

Si quieres una propuesta, postea la estructura de las tabas (o sea el "CREATE TABLE...", no una descripción somera), para poder ver detalles de la relación de las tablas que no se pueden inferir de tu ejemplo.

Tip Final: Es mejor expresarse de modo más "informático" en estos foros, porque si no puede que no se entienda la idea... (sin pretender ofender ): Una consulta, un WHERE no "escucha" o "atiende" un valor, sino que realiza una comparación buscando un parámetro o un valor en un campo. En cualquier caso, puede que usar "escuchar" para esto sea válido en otro foro, pero aquí resulta algo extraño y poco claro.
__________________
¿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; 26/06/2010 a las 15:00
  #3 (permalink)  
Antiguo 26/06/2010, 15:16
 
Fecha de Ingreso: marzo-2008
Mensajes: 100
Antigüedad: 16 años, 1 mes
Puntos: 0
Respuesta: no hace caso a condición

Gracias por contestar, soy consciente de que la consulta es enrevesada y poco eficiente, pero soy absolutamente autodidacta y tengo miles de vicios cogidos y malas prácticas de programación, por eso me pasan estas cosas.

En cuanto a la estructuras están creadas con phpmyadmin, te pongo los campos y explico un poco lo que pretendo:

Tabla misiones
mn varchar(40) Primary Key
design varchar(40)
ot varchar(40
mtgt varchar(40)
mc varchar(40)
tmc varchar(40)
mresult varchar(10)
qf smallint(2)
dd varchar(40)
mtask varchar(10)

Tabla disparos
nick varchar(40)
mn varchar(40)
points int(15)
stat varchar(10)
task varchar(10)
fh double(4,2)

Se trata de los siguiente, la tabla misiones almacena misiones de combate en las que participa gente.
La tabla disparos almacena el nick de esa gente y los resultados obtenidos en esas misiones. Un de esos resultados es el "task", que puede ser Succes, Partial o Failed.
La cuestion es que quiero que me cuente el número de misiones en que cada uno de los participantes (nick) a obtenido un task de Partial. EL problema es que no todas las misiones tienen la misma categoria (ot) y quisiera rescatar cuantos "Partial" ha obtenido cada jugador en un determinado tipo de mision, la consulta original, atendiendo al lka condiciond e tipo de mision y atendiendo al resultado task de la tabla disparos era:

SELECT D.nick,SUM(D.points)AS points,
COUNT((SELECT COUNT(*) FROM misiones M WHERE M.mn = D.mn AND M.ot = 'Official 2' GROUP BY M.mn)) 'of2',
COUNT((SELECT COUNT(*) FROM misiones M WHERE M.mn = D.mn AND (M.ot = 'Official 1' OR M.ot='Official 1-1' OR M.ot='Official 2' OR M.ot='Official 2-2' OR M.ot='111 Sqdn Campaign' OR M.ot='International' OR M.ot='International Campaign') AND D.task='Partial' GROUP BY M.mn)) 'ofpartial'
FROM disparos D GROUP BY D.nick

Gracias nuevamente, (por cierto, ahora que he verbalizado realmente el problema, creo que se me ha ocurrido como simplificarlo bastante) en cualquier caso, gracias de nuevo!!

Por cierto, esta DB gestiona un aplicacion en flex a la que puedes echar un vistazo en http://www.escuadron111.com/web/falc.../ROSTER20.html

Última edición por monokote; 26/06/2010 a las 15:26
  #4 (permalink)  
Antiguo 26/06/2010, 15:47
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 hace caso a condición

Bueno, uno de los problemas que tienes está relacionado con la lógica de las bases de datos, y eso se escapa a veces cuando entras en este territorio sin un poco de formación: Se tiene que aprender por el método prueba/error, y hasta que no deduzcas el error no podrás resolverlo.
El problema es que este tipo de errores es medio evasivo, a veces hasta para los experimentados.

El problema se origina, en esencia, en esta cuestión: Todo usuario tiene o cumple misiones, pero no en todas las misiones declaradas ha habido disparos. Al menos eso es lo que desprende del modelo de datos que posteas.

En tu ejemplo tienes dos tablas, pero se infiere una tercera: Usuarios. Esto es importante porque como la lectura de tablas en las bases de datos es de izquierda a derecha en el FROM, si la primera tabla no tiene referencia a un "nick" en especial, ese no aparecerá en la consulta.
Puntualmente, si el reporte es sobre los usuarios, deberás usar la tabla primaria como inicial. Luego, a esta tabla se la debe cruzar con las misiones, para establecer qué misiones han tenido los usuarios, y recién allí hacer una cruza con la tabla disparos, porque los disparos se producen en las misiones y no por fuera de ellas.
¿Se comprende?

La idea sería que la consulta base fuese algo así:
Código MySQL:
Ver original
  1.    usuarios U INNER JOIN misiones M ON U.nick = M.nick
  2.    LEFT JOIN disparos D ON (D.nick = U.nick AND D.mn = M.mn);
Esto debería devolver un listado por usuario de las misiones y de todos los disparos realizados, siendo que si la misión no tuvo disparos aún, ese dato aparecerá como NULL (de allí el LEFT JOIN: todo lo que esté a la izquierda, coincida o no con la tabla derecha que en este caso es "disparos"). Es importante que ese dato aparezca como NULL en esos casos.
Ahora bien, con esta consulta ya podemos afinar: Quieres los usuarios, por misión, cuando la misión es "Partial", sume los puntos totales por disparo, los del "Official 2" y los del resto como uno solo.
Podría ser algo así:
Código MySQL:
Ver original
  1.     U.nick,  
  2.     M.mn Mision,  
  3.     SUM(D.points) PuntosTotales,  
  4.     SUM(IF()) DisparosOf2,  
  5.     SUM(IF(D.ot IS NOT NULL AND D.ot<> 'Official 2'), 1, 0) DisparosResto
  6.    usuarios U INNER JOIN misiones M ON U.nick = M.nick
  7.    LEFT JOIN disparos D ON (D.nick = U.nick AND D.mn = M.mn)
  8. WHERE D.task = 'Partial'
  9. GROUP BY U.nick;

O bien algo así:
Código MySQL:
Ver original
  1.     U.nick,  
  2.     M.mn Mision,  
  3.     SUM(D.points) PuntosTotales,  
  4.     SUM(IF()) DisparosOf2,  
  5.     SUM(IF(D.ot IS NOT NULL AND D.ot IN ('Official 1', 'Official 1-1', 'Official 2', 'Official 2-2', '111 Sqdn Campaign', 'International', 'International Campaign')), 1, 0) DisparosResto
  6.    usuarios U INNER JOIN misiones M ON U.nick = M.nick
  7.    LEFT JOIN disparos D ON (D.nick = U.nick AND D.mn = M.mn)
  8. WHERE D.task = 'Partial'
  9. GROUP BY U.nick, M.mn;

Creo que podrías probarla, y si no da el resultado esperado podemos afinarla más.
__________________
¿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 26/06/2010, 16:02
 
Fecha de Ingreso: marzo-2008
Mensajes: 100
Antigüedad: 16 años, 1 mes
Puntos: 0
Respuesta: no hace caso a condición

Wow, muchísimas gracias. Me has dado dos o tres apuntes que me van a servir para mejorar mucho. Aún no he probado pero como digo, apuntes como "si el reporte es sobre los usuarios, deberás usar la tabla primaria como inicial", que parecen cosas obvias pero que a veces se escapan, son los que muchas veces te sacan del caos y ponen un poco de orden.

Muchísimas gracias de verdad, me has dado un gran empujón. Ya comentaré los resultados

Etiquetas: condición
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:53.