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

Problema de lógica en base de datos MySQL

Estas en el tema de Problema de lógica en base de datos MySQL en el foro de Mysql en Foros del Web. Saludos a la Comunidad. Tengo un problema de lógica con unas tablas en MySQL. Hace unas horas a través implemente un código en PHP para ...
  #1 (permalink)  
Antiguo 03/01/2012, 19:39
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Problema de lógica en base de datos MySQL

Saludos a la Comunidad.

Tengo un problema de lógica con unas tablas en MySQL.

Hace unas horas a través implemente un código en PHP para realizar unos combobox o selectbox dependientes, todo funciono perfecto.

Ejemplo :



Los resultados listan muy bien. Si selecciono el primer selectbox, los datos se relacionan con el siguiente selectbox y así.

Ejemplo:



El Problema está al momento de solo seleccionar dos selectbox y dejar uno sin valor.
Por ejemplo el último selectbox que es el [3] queda en blanco.

Ejemplo:



Funciona bien cuando se envían 3 valores desde los selectbox.

Funciona mal cuando se envían 2 valores desde los selectbox.

Yo entiendo porqué funciona mal, se debe al tema de la relación de las tablas.

La relación de las tablas están bien, pero en la tabla padre que es donde guarda estos valores, exige que guarde las tres categorías porqué están relacionadas.

No entiendo cual será el método que se utilizaría en este caso.

El error :

Cannot add or update a child row: a foreign key constraint fails (`pl`.`publicaciones`, CONSTRAINT `publicaciones_ibfk_2` FOREIGN KEY (`idDepCategoria`) REFERENCES `depcategorias` (`idDepCategoria`)

La tabla idDepCategoria esta relacionada con la tabla correspondiente.

Por eso me indica el error "Esta relacionada, es una llave foránea" y debe tener un valor por regla.

:( Hasta explicar se hace difícil.

Espero que logren entender mi problema.
  #2 (permalink)  
Antiguo 03/01/2012, 19: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: 17 años
Puntos: 2658
Respuesta: Problema de lógica en base de datos MySQL

El 99% de tu problema es programación, no base de datos. Se resuelve simplemente restringiendo el botón de "Aceptar" que supongo habrás puesto de modo que únicamente esté habilitado si y sólo si todos los valores necesarios han sido seleccionados o llenados.
Eso es lo que se hace siempre en una aplicación. Jamás dejas que en un formulario, un usuario pueda cerrar la operación si no está debidamente completa.
Ese principio entra dentro delo que se denominan buenas prácticas de programación.
En cuanto al tema estrictamente de la base y sus tablas, si y sólo si los elementos de esas selecciones son opcionales, entonces deberías enviar datos nulos a las tablas, pero para ello, ese campo FK debería poder aceptar NULL. Y no es el caso.

Yo, como consejo, te sugiero que resuelvas el tema del selector por medio de programación, tal como te lo explico al principio.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 03/01/2012, 20:06
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Respuesta: Problema de lógica en base de datos MySQL

Muchas Gracias gnzsoloyo por tu respuesta :D


Te explico, sobre el tema de las validaciones están correctas, cada control tiene su validación para que el botón Aceptar funcione correctamente.

En la base de datos, funciona bien cuando envío las tres categorías seleccionadas.

Pero cuando envío solo dos categorías seleccionadas ( Por tema de que no existe una tercera categoría en la base de datos) para seleccionar, aparece el problema.

El error es porqué el campo idDepCategoria esta relacionada.

Imagen de la tabla padre:



Como ves tengo configurada la tabla Tipo Nulo [si]

Pero aún así me indica el error por el tema de la relación.

Envíe un valor de 0 ya que este valor no se relaciona a ningún dato, pero el mensaje con el error persiste.
  #4 (permalink)  
Antiguo 03/01/2012, 20:12
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Respuesta: Problema de lógica en base de datos MySQL

Ops, Acabo de enviar hacer el poblado de datos desde phpmyadmin y sin entrar valor en idDepCategoria y funciono, quedo como NULL.



Voy a revisar mi código!
  #5 (permalink)  
Antiguo 03/01/2012, 20:47
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Respuesta: Problema de lógica en base de datos MySQL

Yap, Ahora si conozco el problema:

Se trata de que a la tabla raíz en el campo idDepCategoría inserto un "0" si no hay valor.

De este modo arroja el mensaje con el problema de las restricciones, pero si inserto con un valor NULL, no arroja ningún problema.


Ahora desde el código hice esto:

if($idDepCategoria == 0) $idDepCategoria = NULL;

El error aún se muestra

Luego aplique esto:

if($idDepCategoria == 0) $idDepCategoria = "NULL";

Y el error todavía persiste =/

De que modo puedo insertar ese valor NULL al campo ?
  #6 (permalink)  
Antiguo 03/01/2012, 20:51
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Respuesta: Problema de lógica en base de datos MySQL

Resuelto con : if($idDepCategoria == 0) $idDepCategoria = 'NULL';

Muchas gracias, aprendí algo nuevo :)
  #7 (permalink)  
Antiguo 03/01/2012, 20:58
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Respuesta: Problema de lógica en base de datos MySQL

Última consulta, ahora va ligada netamente a una consulta de MySQL

Con relación a este mismo tema, necesito listar ahora solamente los que tengan dos categorías:

Realice esto:

Código SQL:
Ver original
  1. `publicaciones`.`idDepCategoria` = `depcategorias`.`idDepCategoria` AND `subcategorias`.`idSubCategoria` = `depcategorias`.`idSubCategoria` OR `publicaciones`.`idDepCategoria` = `NULL`


Código SQL:
Ver original
  1. OR `publicaciones`.`idDepCategoria` = `NULL`

Pero no funciona

Última edición por PublicaLibre; 03/01/2012 a las 21:03
  #8 (permalink)  
Antiguo 03/01/2012, 21:11
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Respuesta: Problema de lógica en base de datos MySQL

Dejaré toda mi consulta mejor:

Código SQL:
Ver original
  1. SELECT * FROM `publicaciones`, `regiones`, `comunas`, `categorias`, `subcategorias`, `depcategorias` WHERE `publicaciones`.`idPublicacion` = `publicaciones`.`idPublicacion` AND `publicaciones`.`idComuna` = `comunas`.`idComuna`  AND `comunas`.`idRegion` = `regiones`.`idRegion` AND  `publicaciones`.`idSubCategoria` = `subcategorias`.`idSubCategoria` AND  `subcategorias`.`idCategoria` = `categorias`.`idCategoria` AND  `publicaciones`.`idDepCategoria` = `depcategorias`.`idDepCategoria` AND `subcategorias`.`idSubCategoria` = `depcategorias`.`idSubCategoria` OR `publicaciones`.`idDepCategoria` = 'NULL' AND activated = '1' ORDER BY `publicaciones`.`idPublicacion`

La consulta me lista todos los otros datos pero no los que en el campo idDepCategoria tiene como valor NULL
  #9 (permalink)  
Antiguo 03/01/2012, 21:27
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Respuesta: Problema de lógica en base de datos MySQL

Lo que hice fue:

Código SQL:
Ver original
  1. OR `publicaciones`.`idDepCategoria` IS NULL

Pero la base de datos se desbordo.
  #10 (permalink)  
Antiguo 03/01/2012, 22:41
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Respuesta: Problema de lógica en base de datos MySQL

Y continuo, pero nada :(

No comprendo como realizar la consulta efectiva

Código SQL:
Ver original
  1. OR  `categorias`.`idCategoria` = `subcategorias`.`idCategoria` AND `subcategorias`.`idCategoria` = `categorias`.`idCategoria` AND `publicaciones`.`idDepCategoria` IS NULL
  #11 (permalink)  
Antiguo 04/01/2012, 03:52
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: Problema de lógica en base de datos MySQL

El problema es que estás haciendo un JOIN (la coma), cuando lo que deberías hacer es un LEFT JOIN, de modo que devuelva NULL donde no hay coincidencias.

No tengo la consulta completa, por lo que voy a simplificar el planteo.
Cuando usas la coma (para mi pésima costumbre), estás haciendo lo que se denomina JOIN implícito. En ese caso MySQL realiza una junta natural entre las tablas devolviendo todo lo que coincide entre campos del mismo nombre de las diferentes tablas. Por eso requiere que, para evitar productos cartesianos, indiques qué campos se deben tomar en cuenta.
Pero en esencia la coma es un INNER JOIN. Sólo devuelve lo totalmente coincidente y no las excepciones. Para ese caso existen los LEFT JOIN y RIGHT JOIN, pero tienen una sitaxis algo diferente y a veces complicada de entender.
El caso sería más o menos así:
Código SQL:
Ver original
  1. SELECT *
  2. FROM publicaciones P
  3.     LEFT JOIN depcategorias D ON P.`idDepCategoria` = D.`idDepCategoria`
  4.      LEFT JOIN `subcategorias` S ON D.`idSubCategoria` = S.`idSubCategoria`
Como suelo comentar, en el SQL el orden de los factores sí altera el producto, y este es un ejemplo.
LEFT JOIN devuelve todo lo que exista en la tabla a la izquierda del LEFT JOIN, tenga o no coincidencias con lo que está a la derecha; de la tabla derecha devuelve los registros válidos y el resto serán NULL.
Pero cuidado: El segundo LEFT JOIN sólo devolverá registros si y sólo si a) haces el LEFT JOIN contra la primera tabla, o b) la segunda tabla devuelve valores no nulos y sólo podrá hacerlo contra esos valores no nulos.

Esto significa que si publicaciones devolviese 50 registros, y su LEFT JOIN contra depcategorias devolviese 32 no nulos, el LEFT JOIN contra subcategorías sólo usará esos 32 registros para hacer su tarea y pondrá NULL en el resto.
¿Se va entendiendo?

Esto sucede porque NULL no es un dato, sino un estado de indefinición (o puntero a la nada), y no puedes hacer operaciones de ningún tipo con las indefiniciones. Entonces simplemente las ignora.

Ten cuidado con las operaciones donde se presente un NULL. Si haces una suma directa contra un campo que contiene NULL, el resultado será siempre NULL.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #12 (permalink)  
Antiguo 04/01/2012, 20:04
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Respuesta: Problema de lógica en base de datos MySQL

Te agradezco infinitamente por tu respuesta :)

Funciona muy bien está consulta, pero debo ahora complementarla con el resto :D

Código SQL:
Ver original
  1. SELECT *
  2. FROM publicaciones P
  3.   LEFT JOIN depcategorias D ON P.`idDepCategoria` = D.`idDepCategoria`
  4.   LEFT JOIN `subcategorias` S ON D.`idSubCategoria` = S.`idSubCategoria`


He intentado unirla con el resto de la consulta que tengo, pero la falta de conocimientos de MySQL se hace presente en mí y todavía no logro hacerlo funcionar :(

Sinceramente me falta mucho que aprender sobre MySQL, por eso mismo me tomaré un buen tiempo para estudiar en profundidad este lenguaje :)

Bueno te dejo toda mi consulta, (esta consulta funciona bien, pero solo con 3 categorías y no lista los valores con NULL)
Y con mi bajo conocimiento me complicada transformarla con el LEFT JOIN

Código SQL:
Ver original
  1. SELECT
  2.                                    `publicaciones`.`idPublicacion`  AS id_publicacion,
  3.                                    `publicaciones`.`nombre`         AS nombre_publicacion,
  4.                                    `publicaciones`.`email`          AS email_publicacion,
  5.                                    `publicaciones`.`titulo`         AS titulo_publicacion,
  6.                                    `publicaciones`.`activated`      AS activated_publicacion,
  7.                                    `publicaciones`.`tipoPlan`       AS tipo_plan,
  8.                                    `regiones`.`nombre`              AS nombre_region
  9.         FROM `publicaciones`, `regiones`, `comunas`, `categorias`, `subcategorias`, `depcategorias` WHERE `publicaciones`.`idPublicacion` = `publicaciones`.`idPublicacion` AND `publicaciones`.`idComuna` = `comunas`.`idComuna`  AND `comunas`.`idRegion` = `regiones`.`idRegion` AND  `publicaciones`.`idSubCategoria` = `subcategorias`.`idSubCategoria` AND  `subcategorias`.`idCategoria` = `categorias`.`idCategoria` AND  `publicaciones`.`idDepCategoria` = `depcategorias`.`idDepCategoria` AND `subcategorias`.`idSubCategoria` = `depcategorias`.`idSubCategoria` AND activated = '1' ORDER BY `publicaciones`.`idPublicacion` DESC

En caso de hacer la prueba dejaré el acceso a phpmyadmin abierto

La base de datos se llama pl

Usuario: usuario
Contraseña: 123456

http://200.83.31.180/phpmyadmin/



Muy agradecido nuevamente por la gran ayuda y el tiempo que se toma en esto :)

Saludos.

Última edición por PublicaLibre; 04/01/2012 a las 20:58
  #13 (permalink)  
Antiguo 05/01/2012, 16:28
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: Problema de lógica en base de datos MySQL

El problema sucede cuando intentas ver las tres tablas como si fuesen un sólo resultado, cosa que no es así.
Cuando haces un JOIN con más de dos tablas (esto se planteo con otro forista hace unas semanas), lo que tienes que entender es que el segundo JOIN no opera en conjunto sino que lo hace con la tabla resultado (o tabla derivada) del primer JOIN.
Esto significa que si el primer LEFT JOIN devuelve resultados válidos además de los NULL, será sobre esos resultados válidos como tabla virtual, donde se hace el siguiente LEFT JOIN. Y como no se puede hacer un JOIN de ningún tipo contra NULL, sólo devolverá aquellos registros que coincidan con valores reales devueltos por la segunda tabla.
¿Se entiende?
La única posibilidad de que no ocurra eso, es que el segundo LEFT JOIN apunte a una relación entre la primera y tercera tablas directamente.

Una curiosidad es que en los hechos, este LEFT JOIN doble te devolverá el mismo resultado que si hubieses hecho primero un INNER JOIN y luego un LEFT JOIN...

Ahora bien, hay una nota más: Si haces un LEFT JOIN entre la primera y la segunda, seguido de un LEFT JOIN entre la primera y la tercera tablas, en realidad peude devolverte resultados falsos, porque generará un producto cartesiano en el primero JOIN... Es decir, repetirá los resultados del primer LEFT JOIN... varias veces. La explicación de esto es un poquitín complicada, pero en resumen, para hacerlo así habría que resolver el primer LEFT JOIN como una subconsulta...

Como verás, la cosa se complica a medida que agregas JOINs.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #14 (permalink)  
Antiguo 06/01/2012, 00:26
 
Fecha de Ingreso: enero-2012
Mensajes: 15
Antigüedad: 12 años, 10 meses
Puntos: 0
Respuesta: Problema de lógica en base de datos MySQL

gnzsoloyo

Amigo, tremendamente agradecido por toda la gran ayuda. Tus explicaciones excelentes, se nota el gran conocimiento que tienes :D y lo muy buena persona que eres al explicar con cada detalle lo que debo aprender, gracias a tu buena disposición pude aprender lo basico de un LEFT JOIN.

Hace unos minutos logre terminar la consulta, creo que fue satisfactoria, la he probado y ahora si funciona bien, he poblado la base de datos y muestra los datos reales y sin duplicados. Parece que todo funciona bien con esta consulta que modifique gracias a tu ayuda :D

Código SQL:
Ver original
  1. SELECT
  2.                 P.`idPublicacion`   AS id_publicacion,
  3.                 P.`nombre`          AS nombre_publicacion,
  4.                 P.`email`           AS email_publicacion,
  5.                 P.`telefono`        AS telefono_publicacion,
  6.                 P.`titulo`          AS titulo_publicacion,
  7.                 P.`contenido`       AS contenido_publicacion,
  8.                 P.`precio`          AS precio_publicacion,
  9.                 P.`tipoPlan`        AS tipo_plan,
  10.                 P.`tiempo`          AS tiempo_publicacion,
  11.                 P.`visitas`         AS visitas_publicacion,
  12.                 P.`activated`       AS activated_publicacion,
  13.                 G.`nombre`          AS nombre_categoria,
  14.                 S.`nombre`          AS nombre_subcategoria,
  15.                 D.`nombre`          AS nombre_depcategoria,
  16.                 R.`nombre`          AS nombre_region,
  17.                 C.`nombre`          AS nombre_comuna
  18.                                    
  19.         FROM publicaciones P
  20.                        
  21.                 LEFT JOIN comunas C         ON P.`idComuna` = C.`idComuna`
  22.                 LEFT JOIN regiones R        ON C.`idRegion` = R.`idRegion`
  23.                 LEFT JOIN subcategorias S   ON P.`idSubCategoria` = S.`idSubCategoria`
  24.                 LEFT JOIN categorias G      ON S.`idCategoria` = G.`idCategoria`
  25.                 LEFT JOIN depcategorias D   ON P.`idDepCategoria` = D.`idDepCategoria`
  26.        
  27.         WHERE
  28.                            
  29.                 P.`idPublicacion` = P.`idPublicacion`
  30.         AND
  31.                 P.`activated` = 1
  32.                 ORDER BY P.`idPublicacion` DESC
  33.                 LIMIT $start, $limit

Bueno seguiré modificando mis demás consultas, cambiando las comas por este método.
Luego te digo como va todo :D

Saludos!

Etiquetas: php, select, sql, tabla
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:00.