【问题标题】:MYSQL match multiple rows across same table with multiple idsMYSQL 匹配具有多个 id 的同一张表中的多行
【发布时间】:2019-01-18 21:40:53
【问题描述】:

我正在研究一种处理订单的方法,我必须满足来自多个供应商的订单,并且我想知道哪 2 个供应商可以提供给定的订单。

我订单中的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

等等……

【问题讨论】:

  • 考虑处理应用程序代码中的显示问题
  • 是的。不担心显示问题。只是想得到结果:)

标签: mysql sql match where-in


【解决方案1】:

你想要group byhaving

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;

注意:如果一个供应商拥有所有产品,那么它将与所有其他供应商配对。

【讨论】:

  • 谢谢,戈登。我正在寻找更广阔的东西。所以订单输入可以改变产品和尺寸,我可以通过变量等来适应。但在大多数情况下,很少有一个供应商拥有所有物品,就像在我的示例中,没有供应商拥有全部 5 个。所以如何匹配 2 个供应商以满足所有 5 个产品?
  • @DanielGurzi 。 . .哦,这让这个问题变得更有趣了。
  • 哇。我还在检查它。我的数据库非常大,所以这需要一段时间才能完成。与此同时,我试图弄清楚这一切意味着什么。你能解释一下 n.n = 1 以及它在做什么吗?一旦完成,我会给你发送一个更最终的版本,以更多地展示它在野外是如何工作的
  • @DanielGurzi 。 . .该子查询连接了两个供应商。对于这两项工作,产品需要在不同的行上,每行有两个供应商 ID(即“A, 1”/“B, 2” --> “A, B, 1”/“A, B,2")。 CROSS JOINnCASE 用于此反透视。
  • 感谢您的帮助。我可以在这里使用你的一些想法。最终,我最终做了更长更难的事情,大声笑,但它的工作速度非常快。本质上,我查看了每个供应商缺少的内容,然后将第二个供应商与这些缺少的项目匹配。它给了我一个第二个供应商的列表来与每个初始供应商配对。我看看能不能写出来简单分享一下
猜你喜欢
  • 1970-01-01
  • 2016-11-01
  • 1970-01-01
  • 2021-06-08
  • 1970-01-01
  • 2014-08-09
  • 2023-03-08
  • 1970-01-01
  • 2021-09-20
相关资源
最近更新 更多