mysql - MYSQL 匹配具有多个 id 的同一张表中的多行
问题描述
我正在研究一种处理订单的方法,我必须满足来自多个供应商的订单,并且我想知道哪两个供应商可以提供给定的订单。
我订单中的 product_ids 是 10,20,30,40,50
SELECT *
FROM vendors
WHERE product_id IN (10,20,30,40,50)
给我所有至少拥有 1 种产品的供应商
vendor_id | product_id
1234 10
1234 20
1234 30
1234 40
1235 10
1235 40
1236 20
1236 30
1236 40
1237 50
9876 10
9876 20
9876 30
9876 40
9877 10
9877 40
9877 50
9878 10
9878 20
9878 30
9878 50
经过几个疯狂的子查询(太长无法在此处发布),我可以找到一个表格,显示每个供应商缺少的内容,然后我的想法是根据那些缺少的项目加入该表格,然后显示具有精致的供应商列表。
结果应该看起来像(逗号分隔与否无关紧要,更容易阅读)
vender_1 | product_id | missing_product_id | vendor_2
1234 10,20,30,40 50 9876,9878
1235 10,40 20,30,50 9878
1236 20,30,40 10,50 9877
1237 50 10,20,30,40 1234
或者
vender_1 | product_id | missing_product_id | vendor_2
1234 10
1234 20
1234 30
1234 40
1234 50 9876
1234 50 9878
ETC...
解决方案
你想要group by
并且having
:
SELECT v.vendor_id
FROM vendors v -- Shouldn't this be called vendorProducts ?
WHERE v.product_id IN (10, 20, 30, 40, 50)
GROUP BY v.vendor_id
HAVING COUNT(DISTINCT v.product_id) = 5;
对于多个供应商,您可以扩展上述逻辑。这个想法是将表格连接在一起以获得供应商对的列表以及他们一起拥有的所有产品。然后,执行与上述相同的逻辑:
SELECT v.vendor_id1, v.vendor_id2
FROM (SELECT DISTINCT v1.vendor_id as vendor_id1, v2.vendor_id as vendor_id2,
(CASE WHEN n.n = 1 THEN v1.product_id ELSE v2.product_id END) as product_id
FROM vendors v1 JOIN
vendors v2
ON v1.product_id <> v2.product_id AND
v1.vendor_id < v2.vendor_id CROSS JOIN
(SELECT 1 as n UNION ALL SELECT 2) n
UNION ALL
-- Then include the singletons, just in case
SELECT v.vendor_id, NULL, v.product_id
FROM vendors v
) v
WHERE v.product_id IN (10, 20, 30, 40, 50)
GROUP BY v.vendor_id1, v.vendor_id2
HAVING COUNT(DISTINCT v.product_id) = 5;
您实际上可以在子查询中进行产品过滤——以提高查询效率。至于使这个更笼统,“5”是项目的数量。我不知道最终查询是如何构建的。
编辑二:
这是一个有大量数据的难题。如果您有很多产品和少数供应商,这是另一种可能效果更好的方法:
select v1.*, v2.*
from (select vendor_id,
max(product_id = 1) as p1,
max(product_id = 2) as p2,
max(product_id = 3) as p3,
max(product_id = 4) as p4,
max(product_id = 5) as p5,
from vendors
where product_id in (1, 2, 3, 4, 5)
group by vendor_id
) v1 join
(select vendor_id,
max(product_id = 1) as p1,
max(product_id = 2) as p2,
max(product_id = 3) as p3,
max(product_id = 4) as p4,
max(product_id = 5) as p5,
from vendors
where product_id in (1, 2, 3, 4, 5)
group by vendor_id
) v2
on (v1.p1 + v2.p1) > 0 and
(v1.p2 + v2.p2) > 0 and
(v1.p3 + v2.p3) > 0 and
(v1.p4 + v2.p4) > 0 and
(v1.p5 + v2.p5) > 0;
注意:如果一个供应商拥有所有产品,那么它将与其他所有供应商配对。
推荐阅读
- image - 如何从 Rust 中的 camera_capture 灰度图像
- ios - cordova-plugin-purchase:即使在调用命令之后,iOS 也不做任何事情
- azure - Fluentd 不输出到文件
- javascript - D3从节点隐藏.text元素
- java - 如何在android中打开日期选择器时设置默认年份(但是在滚动年份时它需要显示其他年份直到当前年份)
- python - 如何捕获包含在 boost python 模块中的 C++ 代码中抛出的 Python 异常
- java - Eclipse Gradle 不支持请求的构建类型“java-library”
- amazon-web-services - AWS 云形成。从帐户架构创建堆栈
- javascript - Vuex 持久化认证状态
- node.js - 将缓冲区转换为 blob 并将其设置为 Nodejs 中的 FormData