【问题标题】:Postgresql select related tags (many to many)Postgresql 选择相关标签(多对多)
【发布时间】:2017-10-13 17:29:34
【问题描述】:

我有一个名为 review 的 VIEW,它与汽车表相关,并且汽车表与表标签有多对多关系(通过名为 cars_tags 的连接表),但我需要的是从汽车中检索评论它们与一些标签相关,同时与另一个标签相关。我今天的SQL代码如下:

SELECT  "cars"."review".* 
FROM "cars"."review" 
    LEFT JOIN cars.cars ON (cars.review.car_id = cars.cars.id) 
    LEFT JOIN cars.makes ON (cars.cars.make_id = cars.makes.id) 
    LEFT JOIN cars.cars_tags ON (cars.cars.id = cars.cars_tags.car_id) 
    LEFT JOIN cars.tags ON (cars.cars_tags.tag_id = cars.tags.id) 
WHERE (cars.tags.id IN ('91782e95-8c5d-4254-82ab-b11a21306c18')) 
    AND (cars.tags.id IN ('031cec30-df27-471e-858d-53c3d9657c8a')) 
ORDER BY "cars"."review"."score" DESC LIMIT 100

这个 SQL 没有给我带来任何结果,但我确信有与第一个 id 相关的汽车:'91782e95-8c5d-4254-82ab-b11a21306c18'AND '031cec30-df27-471e-858d-53c3d9657c8a'时间。

我做错了什么?

【问题讨论】:

  • 您的查询是说 - “只带回 cars.tags.id 在 '917...' 和 cars.tags.id 同时在 '031...' 中的结果”。当然,没有一个标签可以同时是两个不同的东西!试试cars.tags.id in ('917...', '031...'),它实际上是说“带回与这些条件中的任一匹配的标签”
  • 但我真正需要的是与 ONE ID 和 OTHER ID 同时相关的结果
  • 我误会了你——没有什么能满足 X = 'A' AND X = 'B'。你所说的“相关”是什么意思?编辑:等等,我想我明白了,给我一分钟

标签: sql postgresql relationship


【解决方案1】:

bool_or

select r.col1, r.col2 
from
    cars.review r
    left join
    cars.cars on r.car_id = cars.id
    inner join
    cars.cars_tags on cars.id = cars_tags.car_id
    inner join
    cars.tags on cars_tags.tag_id = tags.id 
group by r.col1, r.col2 
having
    bool_or (tags.id = '91782e95-8c5d-4254-82ab-b11a21306c18')
    and
    bool_or (tags.id = '031cec30-df27-471e-858d-53c3d9657c8a')
order by r.score desc
limit 100

exists版本:

select col1, col2 
from cars.review
where exists (
    select 1
    from 
        cars.cars
        inner join
        cars.cars_tags on cars.id = cars_tags.car_id
        inner join
        cars.tags on cars_tags.tag_id = tags.id
    where review.car_id = cars.id
    group by 1
    having
        bool_or (tags.id = '91782e95-8c5d-4254-82ab-b11a21306c18')
        and
        bool_or (tags.id = '031cec30-df27-471e-858d-53c3d9657c8a')
)
order by score desc
limit 100

【讨论】:

  • 这很好用,但是我的表格字段太多,无法为每个表格使用分组依据。但是谢谢,我会使用它
  • @AndréCavallari 检查exists 版本
【解决方案2】:

据我了解,您对具有 2 个特定标签的汽车的评论感兴趣。

这可以通过下面的查询来完成。我已经删除了对 cars.make 的引用,因为您没有从中检索任何数据。此外,我删除了对 cars.tags 的引用,因为您使用的唯一信息是 cars_tags 表中的标签 ID。

SELECT  "cars"."review".* 
FROM "cars"."review"
WHERE 
EXISTS (SELECT * FROM cars.cars_tags 
        WHERE cars.cars_tags.car_id = cars.review.cars_id 
        AND cars.cars_tags.tag_id = '91782e95-8c5d-4254-82ab-b11a21306c18')
AND
EXISTS (SELECT * FROM cars.cars_tags 
        WHERE cars.cars_tags.car_id = cars.review.cars_id 
        AND cars.cars_tags.tag_id = '9031cec30-df27-471e-858d-53c3d9657c8a')
ORDER BY "cars"."review"."score" DESC LIMIT 100

该查询只查找存在针对您所追求的两个 tag_id 的 cars_tags 条目的所有评论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 2017-09-26
    • 2012-05-18
    • 1970-01-01
    • 2010-10-17
    相关资源
    最近更新 更多