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

Algunos registros repetidos en consulta

Estas en el tema de Algunos registros repetidos en consulta en el foro de Mysql en Foros del Web. Buenas. Tengo el siguiente problema: Tengo una consulta que en su estructura principal me funciona super bien, yo le llamo la consulta basica: @import url("http://static.forosdelweb.com/clientscript/vbulletin_css/geshi.css"); ...
  #1 (permalink)  
Antiguo 26/06/2013, 14:53
 
Fecha de Ingreso: abril-2011
Mensajes: 66
Antigüedad: 13 años
Puntos: 7
Algunos registros repetidos en consulta

Buenas.

Tengo el siguiente problema:

Tengo una consulta que en su estructura principal me funciona super bien, yo le llamo la consulta basica:

Código MySQL:
Ver original
  1.     bodfam.descripcion AS familia,
  2.     bodestart.descripcion AS 'nombre_estado_articulo',
  3.     bum.descripcion AS unidad_medida,
  4.     bodmar.descripcion AS marca,
  5.     bodmod.descripcion AS modelo,
  6.     bodart.*
  7. FROM bdsistema.bodega_articulo bodart
  8. LEFT JOIN bdsistema.bodega_familia bodfam ON bodfam.id_interno = bodart.id_familia
  9. LEFT JOIN bdsistema.bodega_unidad_medida bum ON bum.id_interno = bodart.id_unidad
  10. LEFT JOIN bdsistema.bodega_marca bodmar ON bodmar.id_interno = bodart.id_marca
  11. LEFT JOIN bdsistema.bodega_modelo bodmod ON bodmod.id_interno = bodart.id_modelo
  12. LEFT JOIN bdsistema.bodega_estado bodestart ON bodestart.id_interno = bodart.estado_articulo

Ahoar os explico la construccion de las BD:

Tengo una BD de articulos, la cual contiene su id_interno y todos sus campos que pertenecen a las caracteristicas del articulo.
Tengo la BD de unidad_medida, que simplemnte enlaza con la tabla articulos, en la cual tengo definido simplemente un id_interno y una descripcion que corresponde a las unidades de medida.
Tengo la BD's de marcas, modelo y estado, que hacen exactamente lo mismo que la anterior.
El problema es cuando a la consulta le agrego la tabla de etiquetas_articulo, que es una tabla que contiene las etiquetas de los articulos. Esta tabla esta a su vez desglosada en la tabla etiquetas, que contiene el id_interno y la descripcion de las etiquetas, y en la tabla etiquetas_articulos, guardo el id de la tabla etiquetas mas el id del articulo. Pero cuando a dos o mas articulos le defino etiquetas, la consulta que les mencione me arroja por ejemplo el sigueinte resultado.

id_articulo nombre_articulo
1 ampolleta 12 volts
2 ampolleta 10 volts
3 ampolleta 15 volts
3 ampolleta 15 volts

Lo que sucede, y el porque me arroja esto es porque a los articulos 1 y 2, les defini una etiqueta, pero al 3 articulo no le defini etiqueta.
La consulta final seria esta:

Código MySQL:
Ver original
  1.     bodfam.descripcion AS familia,
  2.     bodestart.descripcion AS 'nombre_estado_articulo',
  3.     bum.descripcion AS unidad_medida,
  4.     bodmar.descripcion AS marca,
  5.     bodmod.descripcion AS modelo,
  6.     bodart.*
  7. FROM bdsistema.bodega_articulo bodart
  8. LEFT JOIN bdsistema.bodega_familia bodfam ON bodfam.id_interno = bodart.id_familia
  9. LEFT JOIN bdsistema.bodega_unidad_medida bum ON bum.id_interno = bodart.id_unidad
  10. LEFT JOIN bdsistema.bodega_marca bodmar ON bodmar.id_interno = bodart.id_marca
  11. LEFT JOIN bdsistema.bodega_modelo bodmod ON bodmod.id_interno = bodart.id_modelo
  12. LEFT JOIN bdsistema.bodega_estado bodestart ON bodestart.id_interno = bodart.estado_articulo
  13. LEFT JOIN bdsistema.bodega_etiqueta_articulo bodetiart ON bodetiart.id_articulo = bodart.id_interno
  14. LEFT JOIN bdsistema.bodega_etiquetas bodeti ON bodeti.id_interno = bodetiart.id_etiqueta

Si se dan cuenta, ahora le agregue las tablas etiqeta_articulo y etiquetas. Esta consulta es la que me devuelve los registros que mas arriba menciono.

Ahora averiguando y leyendo por ahi, pude encontrar esto que me podria solucionar el problema: Realizrlo con FULL OUTER JOIN

El problema es que MySQL al parecer no soporta FULL OUTER JOIN. Otra solucion, emular el FULL OUTER JOIN. Quedaria como:

Código MySQL:
Ver original
  1.     bodfam.descripcion AS familia,
  2.     bodestart.descripcion AS 'nombre_estado_articulo',
  3.     bum.descripcion AS unidad_medida,
  4.     bodmar.descripcion AS marca,
  5.     bodmod.descripcion AS modelo,
  6.     bodart.*
  7. FROM bdsistema.bodega_articulo bodart
  8. LEFT JOIN bdsistema.bodega_familia bodfam ON bodfam.id_interno = bodart.id_familia
  9. LEFT JOIN bdsistema.bodega_unidad_medida bum ON bum.id_interno = bodart.id_unidad
  10. LEFT JOIN bdsistema.bodega_marca bodmar ON bodmar.id_interno = bodart.id_marca
  11. LEFT JOIN bdsistema.bodega_modelo bodmod ON bodmod.id_interno = bodart.id_modelo
  12. LEFT JOIN bdsistema.bodega_estado bodestart ON bodestart.id_interno = bodart.estado_articulo
  13. LEFT JOIN bdsistema.bodega_etiqueta_articulo bodetiart ON bodetiart.id_articulo = bodart.id_interno
  14. LEFT JOIN bdsistema.bodega_etiquetas bodeti ON bodeti.id_interno = bodetiart.id_etiqueta
  15.     bodfam.descripcion AS familia,
  16.     bodestart.descripcion AS 'nombre_estado_articulo',
  17.     bum.descripcion AS unidad_medida,
  18.     bodmar.descripcion AS marca,
  19.     bodmod.descripcion AS modelo,
  20.     bodart.*
  21.     bdsistema.bodega_articulo bodart LEFT
  22.     JOIN bdsistema.bodega_familia bodfam ON bodfam.id_interno = bodart.id_familia LEFT
  23.     JOIN bdsistema.bodega_unidad_medida bum ON bum.id_interno = bodart.id_unidad LEFT
  24.     JOIN bdsistema.bodega_marca bodmar ON bodmar.id_interno = bodart.id_marca LEFT
  25.     JOIN bdsistema.bodega_modelo bodmod ON bodmod.id_interno = bodart.id_modelo LEFT
  26.     JOIN bdsistema.bodega_estado bodestart ON bodestart.id_interno = bodart.estado_articulo
  27. RIGHT JOIN bdsistema.bodega_etiqueta_articulo bodetiart ON bodetiart.id_articulo = bodart.id_interno
  28. LEFT JOIN bdsistema.bodega_etiquetas bodeti ON bodeti.id_interno = bodetiart.id_etiqueta

El problema hasta aqui, solucionado, pero cuando se me complica, es cuando a la consulta le agrego los parametros de busqueda o de filtrado de datos con la condicion WHERE, porque si quiero filtrar, por ejemplo, por todas las ampolletas en que cuya etiqueta sea "carroceria", deberia mostrarme dos articulos, pero al momento de agregarlos a la consulta, solo me muestra el articulo que no tiene etiquetas. Por ejemplo asi:

Código MySQL:
Ver original
  1.     bodfam.descripcion AS familia,
  2.     bodestart.descripcion AS 'nombre_estado_articulo',
  3.     bum.descripcion AS unidad_medida,
  4.     bodmar.descripcion AS marca,
  5.     bodmod.descripcion AS modelo,
  6.     bodart.*
  7. FROM bdsistema.bodega_articulo bodart
  8. LEFT JOIN bdsistema.bodega_familia bodfam ON bodfam.id_interno = bodart.id_familia
  9. LEFT JOIN bdsistema.bodega_unidad_medida bum ON bum.id_interno = bodart.id_unidad
  10. LEFT JOIN bdsistema.bodega_marca bodmar ON bodmar.id_interno = bodart.id_marca
  11. LEFT JOIN bdsistema.bodega_modelo bodmod ON bodmod.id_interno = bodart.id_modelo
  12. LEFT JOIN bdsistema.bodega_estado bodestart ON bodestart.id_interno = bodart.estado_articulo
  13. LEFT JOIN bdsistema.bodega_etiqueta_articulo bodetiart ON bodetiart.id_articulo = bodart.id_interno
  14. LEFT JOIN bdsistema.bodega_etiquetas bodeti ON bodeti.id_interno = bodetiart.id_etiqueta
  15.     INSTR(bodeti.descripcion, 'carroceria') > 0
  16.     bodfam.descripcion AS familia,
  17.     bodestart.descripcion AS 'nombre_estado_articulo',
  18.     bum.descripcion AS unidad_medida,
  19.     bodmar.descripcion AS marca,
  20.     bodmod.descripcion AS modelo,
  21.     bodart.*
  22.     bdsistema.bodega_articulo bodart LEFT
  23.     JOIN bdsistema.bodega_familia bodfam ON bodfam.id_interno = bodart.id_familia LEFT
  24.     JOIN bdsistema.bodega_unidad_medida bum ON bum.id_interno = bodart.id_unidad LEFT
  25.     JOIN bdsistema.bodega_marca bodmar ON bodmar.id_interno = bodart.id_marca LEFT
  26.     JOIN bdsistema.bodega_modelo bodmod ON bodmod.id_interno = bodart.id_modelo LEFT
  27.     JOIN bdsistema.bodega_estado bodestart ON bodestart.id_interno = bodart.estado_articulo
  28. RIGHT JOIN bdsistema.bodega_etiqueta_articulo bodetiart ON bodetiart.id_articulo = bodart.id_interno
  29. LEFT JOIN bdsistema.bodega_etiquetas bodeti ON bodeti.id_interno = bodetiart.id_etiqueta
  30.     INSTR(bodeti.descripcion, 'carroceria') > 0

Si se fijan, ambas consultas tienenla condicion where, pero la consulta me arroja solo el articulo que no tiene etiquetas asociadas. Alguien me podria dar in consejo aunque fuera sencillo de como lo podria hacer para que me muestre aquellos articulos de lo cuales estoy buscando por su etiqueta ?

Saludos.

editado PD: al publicar este problema me di cuenta que el titulo es incorrceto, espero me disculpen.

Última edición por max_mouse699; 26/06/2013 a las 14:55 Razón: titulo incorrecto
  #2 (permalink)  
Antiguo 26/06/2013, 15:15
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Algunos registros repetidos en consulta

Hola max_mouse699:

Algunas observaciones.

Primero, ¿ES ABSOLUTAMENTE NECESARIO QUE UTILICES SÓLO LEFT JOIN's?

es decir, ¿puede haber artículos sin unidad_medida, marca, modelo o estado?

Utilizar LEFT JOIN's como lo haces, puede traer problemas... si una relación es mandatoria, es decir que debe existir por fuerza, entonces debes utilizar INNER JOIN's, tal como tienes tu modelo, me da a entender que en realidad el problema está justamente desde el modelado de los datos.

Ahora bien, es algo complicado tratar de entender todo el modelo sobre todo al no tener datos, pero partamos de lo último que dices que funciona... hasta donde alcancé a leer la penúltima consulta funciona y te arroja resultados y lo que pretendes es filtrar, a partir de esos resultados sólo aquellos que cumplan con cierta condición correcto???

Una posible error está en cómo funcionan la UNION entre tablas, podrías comenzar a probar poniendo paréntesis, es decir:

Código:
( SELECT ......
  WHERE
      INSTR(bodeti.descripcion, 'carroceria') > 0
)
UNION
( SELECT ......
  WHERE
      INSTR(bodeti.descripcion, 'carroceria') > 0
)
ya que si no colocas paréntesis, el segundo WHERE lo realiza sobre el resultado de la UNION...

Otra solución sería filtrar hasta el final, también utilizando paréntesis o subconsultas, es decir, algo como esto:

Código:
SELECT * FROM 
(
   Aquí colocas la consulta con el UNION sin filtrar los registros
) T
WHERE 
    INSTR(T.campo, 'carroceria') > 0
Obviamente tendrías que incluir el campo que te interesa filtrar en el SELECT...

Has la prueba y nos comentas.

Saludos
Leo.
  #3 (permalink)  
Antiguo 26/06/2013, 16:03
 
Fecha de Ingreso: abril-2011
Mensajes: 66
Antigüedad: 13 años
Puntos: 7
Respuesta: Algunos registros repetidos en consulta

hola leonardo_josue

Cita:
Primero, ¿ES ABSOLUTAMENTE NECESARIO QUE UTILICES SÓLO LEFT JOIN's?

es decir, ¿puede haber artículos sin unidad_medida, marca, modelo o estado?
Si, puede haber articulos sin marca y sin modelo pero el estado y la unidad_medida tienen que ir si o si, son obligatorias.

Cita:
Utilizar LEFT JOIN's como lo haces, puede traer problemas... si una relación es mandatoria, es decir que debe existir por fuerza, entonces debes utilizar INNER JOIN's, tal como tienes tu modelo, me da a entender que en realidad el problema está justamente desde el modelado de los datos.
La verdad es porque asi con los LEFTMJOIN me funciona, debido a que el inner join, por lo que tengo entendido, me forma como una multiplicidad en los datos cuando los uno con inner. Si encuentras que puede servirme, lo probare.

Cita:
la penúltima consulta funciona y te arroja resultados y lo que pretendes es filtrar, a partir de esos resultados sólo aquellos que cumplan con cierta condición correcto???
Correcto

Probe tus dos soluciones propuestas, y no me resulta. Ahora bien si explique he hice todo ese preambulo anterior, era para que pudieran entender el problema que tenia, y que de acuerdo a una de las soluiones que habia encontrado para que los registros no me aparecieran repetidos era realizar una UNION entre consultas mezcladas con LEFT Y RIGHT JOIN.

Si tienen alguna mejora a mi consulta, no duden en publicarla y las pruebo de inmediato.

Gracias.
  #4 (permalink)  
Antiguo 26/06/2013, 19:07
 
Fecha de Ingreso: mayo-2012
Mensajes: 32
Antigüedad: 11 años, 11 meses
Puntos: 1
Respuesta: Algunos registros repetidos en consulta

Hola si mal no entendí si lo que quieres es obtener los articulos con etiqueta carroceria el inner join tendría que funcionarte, pero solo aplicandolo a la tabla de etiqueta articulos y etiquetas. Yo lo haría así
Código SQL:
Ver original
  1. SELECT
  2.         bodfam.descripcion AS familia,
  3.         bodestart.descripcion AS 'nombre_estado_articulo',
  4.         bum.descripcion AS unidad_medida,
  5.         bodmar.descripcion AS marca,
  6.         bodmod.descripcion AS modelo,
  7.         bodart.*
  8.     FROM bdsistema.bodega_articulo bodart
  9.     LEFT JOIN bdsistema.bodega_familia bodfam ON bodfam.id_interno = bodart.id_familia
  10.     LEFT JOIN bdsistema.bodega_unidad_medida bum ON bum.id_interno = bodart.id_unidad
  11.     LEFT JOIN bdsistema.bodega_marca bodmar ON bodmar.id_interno = bodart.id_marca
  12.     LEFT JOIN bdsistema.bodega_modelo bodmod ON bodmod.id_interno = bodart.id_modelo
  13.     LEFT JOIN bdsistema.bodega_estado bodestart ON bodestart.id_interno = bodart.estado_articulo
  14.     INNER JOIN bdsistema.bodega_etiqueta_articulo bodetiart ON bodetiart.id_articulo = bodart.id_interno
  15.     INNER JOIN bdsistema.bodega_etiquetas bodeti ON bodeti.id_interno = bodetiart.id_etiqueta
  16.  WHERE
  17.       INSTR(bodeti.descripcion, 'carroceria') > 0

ya nada mas al final agrega tu filtro

El union que haces no le veo razón de ser y solo alentarás tu consulta
  #5 (permalink)  
Antiguo 27/06/2013, 08:20
 
Fecha de Ingreso: abril-2011
Mensajes: 66
Antigüedad: 13 años
Puntos: 7
Respuesta: Algunos registros repetidos en consulta

Hola marisolphp.

Muchas gracias por tu respuesta, la probe y el filtyrado de informacion me funciona, tu manera es mas simple, la mia tambien funcionaba pero era mas compleja.

Pero el problema ahora retoma al verdadero titulo del tema. Lo que sucede es que si quito la condicion WHERE con todos sus campos, me muestra solo dos articulos como resultado de la consulta, y debo entender que esos dos articulos, son solo los articulos que tienen asociada alguna etiqueta, los que no tiene asociado etiqueta, no los muestra.

La consulta ahora es como poder mostrar todos los articulos, esto quiere decir, los que estan con etiquetas y los que estan sin etiqueta ?
OJO: cuando yo realice la consulta en un comienzo, en el primer post menciono lo que me ocurre, que se me repiten registros de los articulos que no tienen ninguna asociacion con etiqueta:

Cita:
id_articulo nombre_articulo
1 ampolleta 12 volts
2 ampolleta 10 volts
3 ampolleta 15 volts
3 ampolleta 15 volts
De antemano muchas gracias.
Saludos.
  #6 (permalink)  
Antiguo 27/06/2013, 14:53
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 3 meses
Puntos: 447
Respuesta: Algunos registros repetidos en consulta

Postea datos... de tus tablas... porque sigo si visualizar donde está el problema... por lo que veo tus tablas, aunque muchas, son simples catálogos... con dos o tres datos de cada tabla bastará para darnos una idea de dónde puede estar el problema.

Saludos
Leo.
  #7 (permalink)  
Antiguo 28/06/2013, 11:49
 
Fecha de Ingreso: mayo-2012
Mensajes: 32
Antigüedad: 11 años, 11 meses
Puntos: 1
Respuesta: Algunos registros repetidos en consulta

Cita:
Iniciado por max_mouse699 Ver Mensaje
Hola marisolphp.

Muchas gracias por tu respuesta, la probe y el filtyrado de informacion me funciona, tu manera es mas simple, la mia tambien funcionaba pero era mas compleja.

Pero el problema ahora retoma al verdadero titulo del tema. Lo que sucede es que si quito la condicion WHERE con todos sus campos, me muestra solo dos articulos como resultado de la consulta, y debo entender que esos dos articulos, son solo los articulos que tienen asociada alguna etiqueta, los que no tiene asociado etiqueta, no los muestra.

La consulta ahora es como poder mostrar todos los articulos, esto quiere decir, los que estan con etiquetas y los que estan sin etiqueta ?
OJO: cuando yo realice la consulta en un comienzo, en el primer post menciono lo que me ocurre, que se me repiten registros de los articulos que no tienen ninguna asociacion con etiqueta:



De antemano muchas gracias.
Saludos.
Ahh si lo que quieres es que muestre todos tus articulos y aparte las etiquetas de solo cierto nombre creo que la consulta si sería con left join algo así

Código MySQL:
Ver original
  1.             bodfam.descripcion AS familia,
  2.             bodestart.descripcion AS 'nombre_estado_articulo',
  3.             bum.descripcion AS unidad_medida,
  4.             bodmar.descripcion AS marca,
  5.             bodmod.descripcion AS modelo,
  6.             bodart.*
  7.         FROM bdsistema.bodega_articulo bodart
  8.         LEFT JOIN bdsistema.bodega_familia bodfam ON bodfam.id_interno = bodart.id_familia
  9.         LEFT JOIN bdsistema.bodega_unidad_medida bum ON bum.id_interno = bodart.id_unidad
  10.         LEFT JOIN bdsistema.bodega_marca bodmar ON bodmar.id_interno = bodart.id_marca
  11.         LEFT JOIN bdsistema.bodega_modelo bodmod ON bodmod.id_interno = bodart.id_modelo
  12.         LEFT JOIN bdsistema.bodega_estado bodestart ON bodestart.id_interno = bodart.estado_articulo and INSTR(bodeti.descripcion, 'carroceria') > 0
  13.         left JOIN bdsistema.bodega_etiqueta_articulo bodetiart ON bodetiart.id_articulo = bodart.id_interno
  14.         left JOIN bdsistema.bodega_etiquetas bodeti ON bodeti.id_interno = bodetiart.id_etiqueta

si ves el filtro realmente iría en el left join de la tabla de etiquetas

Otra forma sería un left join con un select, algo así:

Código MySQL:
Ver original
  1.             bodfam.descripcion AS familia,
  2.             bodestart.descripcion AS 'nombre_estado_articulo',
  3.             bum.descripcion AS unidad_medida,
  4.             bodmar.descripcion AS marca,
  5.             bodmod.descripcion AS modelo,
  6.             bodart.*
  7.         FROM bdsistema.bodega_articulo bodart
  8.         LEFT JOIN bdsistema.bodega_familia bodfam ON bodfam.id_interno = bodart.id_familia
  9.         LEFT JOIN bdsistema.bodega_unidad_medida bum ON bum.id_interno = bodart.id_unidad
  10.         LEFT JOIN bdsistema.bodega_marca bodmar ON bodmar.id_interno = bodart.id_marca
  11.         LEFT JOIN bdsistema.bodega_modelo bodmod ON bodmod.id_interno = bodart.id_modelo
  12.         LEFT JOIN  bdsistema.bodega_estado bodestart
  13.  ON bodestart.id_interno = bodart.estado_articulo and
  14.         left JOIN (select * from
  15. bdsistema.bodega_etiqueta_articulo bodetiart
  16.  inner JOIN bdsistema.bodega_etiquetas bodeti ON bodeti.id_interno = bodetiart.id_etiqueta
  17. where INSTR(bodeti.descripcion, 'carroceria') > 0) as tablaeti
  18. ON tablaeti.id_articulo = bodart.id_interno

Lo que importa es que primero tienes que filtrar la tabla de las etiquetas y luego ligarla con tu tabla de articulos
  #8 (permalink)  
Antiguo 05/07/2013, 16:34
 
Fecha de Ingreso: abril-2011
Mensajes: 66
Antigüedad: 13 años
Puntos: 7
Respuesta: Algunos registros repetidos en consulta

@marisolphp: la primera consulta que me mencionas, funciono, nose porque, pero funciono.

Ahora con respecto a colocar datos, se me hizo casi imposible, aunque fueran de prueba, pero el modelo de las tablas lo colgare en el sigueinte post para ver si lo que realizo es lo correcto o no.

Otro error del que me di cuenta, era que la consulta cuando se ejecuta, me inserta varias veces valores que ya tengo almacenados en la tabla, por lo cual eso lo pude solucionar concatenando algunos campos y dejandolos como valores unicos.

Agradezco a todos los participantes de este problema en haberme ayudado.
Gracias.
Salduos.

Etiquetas: campo, join, registros, repetidos, 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 17:16.