postgresql 多对多关系筛选器

55ooxyrt  于 2022-11-04  发布在  PostgreSQL
关注(0)|答案(2)|浏览(151)

我需要使用与另一个表具有多对多关系的类别表筛选查询。是否可以筛选具有多对多关系的查询?
res_partner具有与表res_partner_category.res_partner相关的many2many字段category_id,或者说合作伙伴可以具有许多类别。我需要筛选res_partners表,其中它具有名为“business”或“retail”的类别。如果它不具有这些类别中的任何一个,则不应显示它。
res_partner中还有另一个域是category_value_ids,它与res_partners_category_valueone2many关系:

**res_partner**具有以下带关系的字段:

  • category_idres_partner_category(多对多)
  • category_value_idsres_partner_category_value(一对多)
  • name(字符)
    **res_partner_category**具有以下带关系的字段:
  • partner_idsres_partner(多对多)
  • name(字符)
    **res_partner_category_value**具有以下带关系的字段:
  • category_group_idres_partner_category(多对一)
  • category_idres_partner_category(多对一)
  • object_idres_partner(多对一)

但是,如果我尝试在SQL查询中使用res_partner_category_value表,我会得到错误,我不能在查询中使用它。
例如,如果有4个合作伙伴属于以下类别:

  • 第一:类别1、类别2、业务
  • 第二:零售
  • 第三:零售、商业
  • 第四类:category 1、category 2

查询应返回第一个、第二个和第三个合作伙伴。
一个人告诉我不可能用多对多关系来过滤,所以我想知道这是真的不可能还是很复杂?
编辑:
我又发现了一个叫做res_partner_category_rel的表。我没有看到它,因为在Openerp管理界面中,你可以看到数据库的所有对象,但那个表并没有显示出来。你只能直接通过数据库看到它。所以我被这个“缺失”的表弄糊涂了:

资源合作伙伴类别相关性:

  • partner_id(多对一)
  • category_id(多对一)
lyr7nygr

lyr7nygr1#

设置

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

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;

另一个:

SELECT p.*
FROM        (SELECT partner_id FROM partner_category WHERE category_id = 3) pc1
FULL   JOIN (SELECT partner_id FROM partner_category WHERE category_id = 4) pc2 USING (partner_id)
JOIN   partner p USING (partner_id)
ORDER  BY p.partner_id;

fiddle
古老的SQLFIDLE
第二个假设(partner_id, category_id)partner_category中是唯一的。

6bc51xsx

6bc51xsx2#

正如您已经注意到的,many2one category_id在数据库中不是以表字段的形式表示的,而是以与Partners和Categories相关的表的形式表示的。
您需要的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])])

相关问题