PostgreSQL 1到n关系,查询行,其中n与输入完全匹配
假设我有两张桌子,订单和订单详情。订单详细信息包含订单中订购的产品。为清楚起见,下面有一个示例: 订单:PostgreSQL 1到n关系,查询行,其中n与输入完全匹配,postgresql,relational-division,Postgresql,Relational Division,假设我有两张桌子,订单和订单详情。订单详细信息包含订单中订购的产品。为清楚起见,下面有一个示例: 订单: +----------+ | order_id | +----------+ | 1 | | 2 | | 3 | | 4 | | 5 | +----------+ 订单详情: +----------+-------------+ | order_id | product_id | +----------+-------
+----------+
| order_id |
+----------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+----------+
订单详情:
+----------+-------------+
| order_id | product_id |
+----------+-------------+
| 1 | 1 |
| 1 | 4 |
| 2 | 3 |
| 2 | 4 |
| 3 | 3 |
| 3 | 4 |
| 3 | 5 |
| 4 | 4 |
| 4 | 3 |
+----------+-------------+
如何找到与产品列表完全匹配的订单?
根据上述数据,给定产品列表[3,4],查询应返回两个订单,即2和4。订单3不匹配,因为产品5也已订购
我可以这样做,但感觉好像我错过了什么:
select order_id
from orders_details
group by order_id
having array_agg(product_id) @> array[3, 4] and array_agg(product_id) <@ array[3, 4]
我不太熟悉Postgres的数组语法,但您可以通过使用两个断言的聚合来处理此问题:
SELECT o.order_id
FROM Orders o
INNER JOIN Orders_details od
ON o.order_id = od.order_id
GROUP BY
o.order_id
HAVING
COUNT(CASE WHEN od.product_id NOT IN (3, 4) THEN 1 END) = 0 AND
COUNT(DISTINCT od.product_id) = 2;
HAVING子句中的第一个计数断言,除了3和4之外,没有其他产品标识出现。但这仍然会导致订单只有一个产品id。HAVING子句中的第二个计数断言,实际上存在两个产品id,这意味着是3和4。附加问题:这个特定问题有名称吗?是的,它有名称,甚至有标记。我认为数组解决方案可能是Postgres中最有效的一种。或者,您可以使用按product\u id=array[3,4]排序的array\u aggproduct\u id