【问题标题】:Postgresql Select Rows where associated record with value X or Y does not existPostgresql 选择不存在具有值 X 或 Y 的关联记录的行
【发布时间】:2021-01-10 15:42:01
【问题描述】:

我有 3 张桌子:

Table        columns
---------------------
items        id, name
variations   id, item_id
images       id, variation_id, type

image 有一个variationvariation 有一个item

我想找到没有images type 4 或 5 items(类型是任何整数 0..5 并且不能为 null)

以下查询有效,但它使用 UNION 子查询 带有 NOT IN 约束,我认为这是低效的 - 问题是 因此,编写此查询的更有效方法是什么。

SELECT DISTINCT i.id, i.name 
FROM items i 
INNER JOIN variations v 
  ON v.item_id = i.id 
INNER JOIN images vi 
  ON vi.variation_id = v.id 
WHERE i.id NOT IN (SELECT i.id FROM items i 
                  INNER JOIN variations v 
                    ON v.item_id = i.id 
                  INNER JOIN images vi 
                    ON vi.variation_id = v.id 
                  WHERE vi.type = 4
                  UNION
                  SELECT i.id FROM items i 
                  INNER JOIN variations v 
                    ON v.item_id = i.id 
                  INNER JOIN images vi 
                    ON vi.variation_id = v.id 
                  WHERE vi.type = 5)

解决方案

基于 Gordons 的回答,下面的最终解决方案是:

select i.*
from items i
where not exists (select 1
                  from variations v join
                       images im
                       on v.image_id = im.id
                  where v.item_id = i.item_id and i.type in (4, 5)
                 )
and exists (select 1
                  from variations v join
                       images im
                       on v.id = im.variation_id
                       where v.item_id = i.id)

【问题讨论】:

    标签: sql postgresql subquery inner-join union


    【解决方案1】:

    我想查找没有类型 4 或 5 图像的项目

    根据您的描述,这听起来像not exists

    select i.*
    from items i
    where not exists (select 1
                      from variations v join
                           images im
                           on v.image_id = im.id
                      where v.item_id = i.item_id and i.type in (4, 5)
                     );
    

    【讨论】:

    • 谢谢 Gordon,我对这个解决方案的唯一问题是它偏离了原始查询结果,因为它包含根本没有图像的项目 - 这些也应该被省略(描述可能更清楚)跨度>
    • @mb.Brunel 。 . .您的问题中没有关于该要求的任何内容,我什至在答案中包含了相关部分。当然,您可以添加类似于not existsexists 子句来保证图像存在。
    【解决方案2】:

    使用聚合替代 Gordon 的答案:

    SELECT DISTINCT
        i.id,
        i.name 
    FROM items i 
    INNER JOIN variations v 
        ON v.item_id = i.id 
    INNER JOIN images vi 
        ON vi.variation_id = v.id
    GROUP BY
        i.id
    HAVING
        COUNT(*) FILTER (WHERE vi.type IN (4, 5)) = 0;
    

    请注意,以上假设iditems 表中的主键列。如果不是,那么也许我们应该改用GROUP BY i.id, i.name

    【讨论】:

    • 此解决方案有效,但它比使用 exists 的解决方案慢(在 8000 条记录上测试)执行时间 37.935 毫秒 vs 21.742 毫秒
    • @mb.Brunel 如果您添加适当的索引,我的答案可以大大加快。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 2015-06-01
    • 2021-01-01
    • 1970-01-01
    • 2017-12-24
    相关资源
    最近更新 更多