多对多关系过滤器

时间:2012-11-06 14:45:37

标签: sql postgresql database-design openerp relational-division

我需要使用与另一个表有许多关系的类别表来过滤我的查询。是否可以使用many2many关系过滤查询?

res_partner有许多与表category_id相关的多个字段res_partner_category.res_partner,或者我们只是说合作伙伴可以有多个类别。我需要的是过滤res_partners表,其中包含名为“business”或“retail”的类别。如果它没有任何这些类别,则不应显示。

此外,res_partner中的另一个字段为category_value_ids且与one2manyres_partners_category_value的关系:

res_partner 包含以下关系字段:

  • category_idres_partner_category(many2many)
  • category_value_idsres_partner_category_value(one2many)
  • name(char)

res_partner_category 包含以下关系字段:

  • partner_idsres_partner(many2many)
  • name(char)

res_partner_category_value 包含以下关系字段:

  • category_group_idres_partner_category(many2one)
  • category_idres_partner_category(many2one)
  • object_idres_partner(many2one)

但是如果我尝试在SQL查询中使用res_partner_category_value表,我会收到错误,我无法在查询中使用它。

例如,如果有4个合作伙伴拥有这些类别:

  • first:categ1,categ2,business
  • 第二名:零售
  • 第三名:零售,业务
  • 第四名:categ1,categ2

查询应该返回第一,第二和第三个伙伴 一个人告诉我,不可能像many2many关系这样过滤。所以我想知道它真的不可能或只是复杂吗?

编辑:
我找到了一个名为res_partner_category_rel的表。我没有看到它,因为在Openerp管理界面中,您可以看到数据库的所有对象,该表未显示。您只能通过数据库直接看到它。 所以我对这个“缺失”的表感到困惑:

res_partner_category_rel:

  • partner_id(很多人)
  • category_id(很多人)

2 个答案:

答案 0 :(得分:5)

这是您应该提供的测试用例:

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);

这是您所追求的查询许多可能的变体之一):

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.

这里的关键词是关系划分。在这个相关问题下,我们已经汇集了一整套查询来处理这类问题:

答案 1 :(得分:2)

正如您已经注意到的那样,many2one category_id未在数据库中表示为表字段,而是作为与合作伙伴和类别相关的表格。

您需要的SQL可能如下所示:

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)

如果你想在python对象中进行过滤,那么通常的search调用应该有效:

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

作为奖励,由于类别在树中组织,您可以使用以下类别及其所有孩子:

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