【问题标题】:how to find rows that contains several values from another table如何从另一个表中查找包含多个值的行
【发布时间】:2021-05-18 06:21:38
【问题描述】:

我有两张桌子:

PRODUCTS
| id | name   |
| -- | ------ |
| 1  | pen    |
| 2  | pencil |    

价格

| price | status        | product_id |
| ----- | --------      | ---------- |
| 1.0   | accepted      | 1          |
| 2.0   | closed        | 1          |
| 2.0   | not relevant  | 2          |
| 2.0   | closed        | 2          |

我找到了一种使用子查询的方法:

SELECT * FROM PRODUCTS p
WHERE id in (select product_id FROM PRICES WHERE status = 'accepted')
AND id in (select product_id FROM PRICES WHERE status = 'closed')

但我认为,这不是最好的方法。还有哪些其他方法?是否可以使用 JOIN 或其他没有子查询的东西来做到这一点?

【问题讨论】:

    标签: sql postgresql join


    【解决方案1】:

    我喜欢在这里使用连接聚合方法:

    SELECT p.id, p.name
    FROM PRODUCTS p
    INNER JOIN PRICES pp
        ON pp.product_id = p.id
    WHERE pp.status IN ('accepted', 'closed')
    GROUP BY p.id       -- see note below
    HAVING MIN(pp.status) <> MAX(pp.status);
    

    Demo

    请注意,如果PRODUCTS.id 不是该表的主键/唯一键,那么您应该使用GROUP BY p.id, p.name。否则,GROUP BY p.id 就足够了。

    【讨论】:

      【解决方案2】:

      最有效的方法可能是:

      SELECT p.*
      FROM PRODUCTS p
      WHERE EXISTS (SELECT 1
                    FROM PRICES pr
                    WHERE pr.product_id = p.id AND pr.status = 'accepted'
                   ) AND
            EXISTS (SELECT 1
                    FROM PRICES pr
                    WHERE pr.product_id = p.id AND pr.status = 'closed'
                   );
      

      特别是,这可以利用PRICES(product_id, status) 上的索引。

      注意:性能提升来自于避免聚合。但是,当聚合(仅)通过主键时,Postgres 有一些漂亮的算法。因此,将此解决方案与 Tim 的解决方案进行比较会很有趣。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-10
        • 1970-01-01
        相关资源
        最近更新 更多