varios una tabla solucion relacion muchos llenar intermedia ejemplos como sql postgresql database-design openerp relational-division

sql - una - relacion uno a varios ejemplos



Filtro de relaciĆ³n de muchos a muchos (2)

Necesito filtrar mi consulta con la tabla de categorías que tiene una relación muy variada con otra tabla. ¿Es posible filtrar consultas con muchas relaciones de muchos?

La tabla res_partner tiene many2many field category_id relacionado con la tabla res_partner_category.res_partner , o digamos que los partners pueden tener muchas categorías. Lo que necesito es filtrar la tabla res_partners donde tiene la categoría llamada ''business'' o ''retail''. Si no tiene ninguna de estas categorías, no debería mostrarse.

También hay otro campo en res_partner que es category_value_ids y tiene one2many relación res_partners_category_value con res_partners_category_value :

res_partner tiene los siguientes campos con relaciones:

  • category_id a res_partner_category (many2many)
  • category_value_ids to res_partner_category_value (one2many)
  • name (char)

res_partner_category tiene los siguientes campos con relaciones:

  • partner_ids a res_partner (many2many)
  • name (char)

res_partner_category_value tiene los siguientes campos con relaciones:

  • category_group_id to res_partner_category (many2one)
  • category_id to res_partner_category (many2one)
  • object_id to res_partner (many2one)

Pero si trato de usar la tabla res_partner_category_value en la consulta SQL me sale un error que no puedo usar en la consulta.

Entonces, por ejemplo, si hay 4 socios con estas categorías:

  • primero: categ1, categ2, negocio
  • segundo: venta al por menor
  • tercero: comercio minorista, negocios
  • cuarto: categ1, categ2

La consulta debe devolver primero, segundo y tercer socio.
Una persona me dijo que no es posible filtrar así con muchas relaciones. Entonces me pregunto si realmente no es posible o simplemente es complicado.

EDITAR:
Encontré una tabla más llamada res_partner_category_rel . No lo vi, porque en la interfaz de administración de Openerp, donde puedes ver todos los objetos de la base de datos, esa tabla no se muestra. Solo puede verlo directamente a través de la base de datos. Así que estaba confundido por esta tabla "perdida":

res_partner_category_rel:

  • partner_id (many2one)
  • category_id (many2one)

Como ya ha notado, el many2one category_id no está representado en la base de datos como un campo de tabla, sino como una tabla que relaciona Socios y Categorías.

El SQL que necesita podría verse así:

SELECT p.* FROM res_partner p INNER JOIN res_partner_category_rel rel ON p.id = rel.partner_id INNER JOIN res_partner_category c ON rel.category_id = c.id WHERE c.id in (3,4)

Si desea hacer el filtro en el objeto python, la llamada de search habitual debería funcionar:

list_ids = partner_model.search(cr, uid, [(''category_id'', ''in'', [3,4])])

Como beneficio adicional, dado que las Categorías están organizadas en un árbol, puede obtener esas categorías y todos sus hijos usando:

list_ids = partner_model.search(cr, uid, [(''category_id'', ''child of'', [3,4])])


Este es el caso de prueba que debería haber proporcionado:

CREATE TABLE partner ( partner_id serial PRIMARY KEY , partner text ); INSERT INTO partner (partner) VALUES (''partner1'') , (''partner2'') , (''partner3'') , (''partner4'') ; CREATE TABLE category ( category_id serial PRIMARY KEY , category text ); INSERT INTO category (category) VALUES (''categ1'') ,(''categ2'') ,(''business'') ,(''retail''); CREATE TABLE partner_category ( partner_id int REFERENCES partner(partner_id) , category_id int REFERENCES category(category_id) , CONSTRAINT cat_pk PRIMARY KEY (partner_id, category_id) ); INSERT INTO partner_category (partner_id, category_id) VALUES (1,1), (1,2), (1,3) ,(2,4) ,(3,3), (3,4) ,(4,1), (4,2);

Y esta es la consulta que está buscando (una de las muchas variantes posibles):

SELECT p.* FROM partner p WHERE EXISTS (SELECT * FROM partner_category pc WHERE pc.partner_id = p.partner_id AND pc.category_id = 3) OR EXISTS (SELECT * FROM partner_category pc WHERE pc.partner_id = p.partner_id AND pc.category_id = 4) ORDER BY p.partner_id;

SQL Fiddle.

La palabra clave aquí es división relacional . Hemos reunido todo un arsenal de consultas para tratar esta clase de problemas bajo esta pregunta relacionada: