entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

3votos

Tengo una base de datos de un cliente, la cual no se puede alterar su estructura, en la cual posee una tabla de articulos, una tabla de categorias y por ultimo una tabla donde se relacionan estas dos.

Estoy queriendo decifrar desde hoy como poder hacer para que en una sola consulta poder obtener todos los articulos que estan asignados a, supongamos como ejemplo, las categorias 5 y 7.

Hasta ahora una de las posibles soluciones que se me ocurrio es hacer dos querys diferentes, y ahi habia pensado hacer algo inverso al UNION ALL, donde las que no se encuentren repetidas se eliminen, pero no he podido conseguirlo.

3 Respuestas

2votos

Leonardo-Tadei Puntos227320

Hola,

para estas tablas:

**Articulos**
id  cod     des
1   1   Uno
2   2   Dos
3   3   Tres
4   4   Cuatro

**Categorías**
id  des
1   Categoria 1
2   Categoria 2
3   Categoria 3
4   Categoria 4

**ArticulosCategorias**
id  id_art  id_cat
1   1   1
2   1   3
3   2   2
4   2   4
5   3   1
6   3   2
7   4   1
8   4   2

Esta query obtiene los Artículos que corresponden a la vez a las categorías dadas (la 1 y 2 en el ejemplo):

SELECT A.id, A.cod, A.des, AC.id_cat AS c1, C.des, AC2.id_cat AS c2, C2.des
FROM (Articulos AS A, ArticulosCategorias AS AC, ArticulosCategorias AS AC2, Categorias AS C, Categorias AS C2)
WHERE A.id = AC.id_art
AND A.id = AC2.id_art
AND AC.id_cat = 1 AND AC.id_cat = C.id
AND AC2.id_cat = 2 AND AC2.id_cat = C2.id

El resultado del ejemplo es:

id  cod     des     c1  des     c2  des
3   3   Tres    1   Categoria 1     2   Categoria 2
4   4   Cuatro  1   Categoria 1     2   Categoria 2

No es una query tan genérica como sería de esperar, pero funciona bien y es mucho más eficiente que tirar de un UNION

Saludos cordiales!

0voto

mrczrt comentado

Hola Leonardo, donde encuentro los mensajes privados? es que lo veo en mi mail el mensaje pero no encontre como responder desde safari mobile :D

0voto

jmpineiro comentado

Leo desde ya agradezco tu respuesta, como siempre funciona perfecto.

Estoy probando el rendimiento de la query contra otra que un rato antes que respondas habia armado (no tan bien como vos pero cumple con lo que necesito). Por ahora como el volumen de informacion no es tan grande la query que arme tiene una ventaja de unos 0.003 aca te la dejo para que me digas que te parece:

SELECT a.id FROM articulos AS a INNER JOIN (SELECT a2.id, count(a.id) AS Total_articulos FROM articulos as a2 INNER JOIN articulos_categorias AS ac ON ac.art_id=a2.id WHERE ac.cat_id IN(5,9) GROUP BY a.id) AS ext ON ext.id=a.id WHERE ext.Total_articulos=2

Lo que termino haciendo es que busque que sean 2 las categorias porque con el IN me busca las que pertenecen a una, a otra o a las dos entonces contandolas y poniendo la condicion de que sean 2 me aseguro que si o si me diga los articulos que pertenecen a las dos.

0voto

Leonardo-Tadei comentado

Habría que ver el plan de ejecución de cada query y el uso de datos cacheados. Reiniciando MySQL y corriéndolas en orden inverso, posiblemente los valores te den al revés.

A priori, sospecho que tu query se debería ejecutar algo más lento, ya que tiene que calcular un COUNT, devolver los que sean solo 5, solo 9 y 5 y 9, y luego quedarse solo con los que devuelven dos resultados en vez de uno, con lo que en el mejor de los casos, hay que descartar 2/3 de los datos de la proyección, y auq todos los que tienen categoría 5 y 9 también tienen solo 5 y solo 9.

También con tu query no es posible proyectar los datos de las categorías: agregar las categorías a la query le suma bastante complegidad... pero nunca digiste qué columnas querías proyectar, así que fuí a la solución más compleja.

Saludos!

0voto

mrczrt comentado

Hola que tal.... a ya es que no había entendido la pregunta, si tienes razon Leonardo la interprete mas simple de lo que es :D

3votos

Creo que ésta es mas o menos la idea:

SELECT a.NombreArticulo,c.NombreCategoria FROM Relacion r
     INNER JOIN Articulo a ON a.ArticuloId = r.ArticuloId
     INNER JOIN Categoria c ON c.CategoriaId = r.CategoriaId
         WHERE r.CategoriaId IN (5,7)

0voto

jmpineiro comentado

Desde ya gracias por tu respuesta, pero probandola me surgen un problema, es que me trae todos los articulos que estan en la categoria 5 y la 7 (inclusive los que estan en la 5 y no en la 7 y viceversa).

0voto

daniel_uribe_ayvar comentado

Cambia los INNER JOIN por LEFT OUTER JOIN

1voto

mrczrt Puntos6940

Hola que tal, use IN para poder seleccionar varias categorías (2 y 7 en este ejemplo) y trate de hacer un query lo mas simple :

SELECT articulos.*, categorias.* 
FROM articulos, categorias 
WHERE articulos.id=relacion.id_art AND relacion.id_cat=categorias.id 
AND categorias.cat IN (2,7);

Espero te ayude en algo, saludos.

0voto

jmpineiro comentado

Antes que nada gracias, pero me pasa el mismo problema que con la primera respuesta que postearon me trae los articulos que pertenecen a la categoria 5, a la categoria 7 y a las dos categorias. Lo cual al final no me termina de servir.

Desde ya muchas gracias!

0voto

mrczrt comentado

Ok, lo bueno es que ya Leonardo te ayudo a encontrar el mejor método :D saludos!.

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta