sql性能 - 在一对多表中查找匹配集

时间:2013-10-18 15:01:54

标签: mysql sql performance innodb

我有一个存储SKU集的数据库表。例如,我可能有以下单独的SKU项目:

  • 电路板
  • LED
  • 电池连接器

现在我可以单独出售这些物品,或者我可以将它们作为最终产品出售,即我将它们焊接在一起然后张贴。 (这只是一个例子,所以请不要发表评论,让人们自己将它们焊接在一起)。

然而,使用SKU,您可以创建所有可能的项目组合,因此您可以将这三个项目分开,两个一起,三个一起等等。所以这里没有进一步说明我的SKU表:

TABLE `skus`

id | name
 1 : Circuit Board
 2 : LED
 3 : Battery Connector
 4 : Circuit Board + LED
 5 : Circuit Board + Battery Connector
 6 : Circuit Board + LED + Battery Connector

因此我们将所有组合作为可销售单位。现在除此之外,我想知道哪些SKU构建了这些集合,以便我可以允许用户在网站上构建他们的电子设备,并且系统知道项目的集体结果是什么。所以我创建了一个sku_sets表。

TABLE `sku_sets`

id | collective_sku_id | child_sku_id
 1 :         4         :       1
 2 :         4         :       2
 3 :         5         :       1
 4 :         5         :       3
 5 :         6         :       1
 6 :         6         :       2
 7 :         6         :       3

此表现在允许我找出构建sku 4,5,6的内容。

当用户因此选择网站上的电路板,LED和电池连接器并指定他们想要预先构建的项目时,我需要系统能够确定符合该规范的SKU是6号。

到目前为止,我已经解决了以下问题:

SELECT `collective_sku_id`
FROM  `sku_sets` 
WHERE `collective_sku_id` IN (
    SELECT `collective_sku_id`
    FROM `sku_sets`
    GROUP BY `collective_sku_id`
    HAVING COUNT( `collective_sku_id` ) = 3 // the number of SKU components
)
AND `child_sku_id` IN ( 1, 2, 3 ) 
GROUP BY `collective_sku_id`;

正如您所看到的,我在中间使用了一个子查询,它将从sku_sets表中读取所有行,然后查找哪些行有collective_sku_id三次出现(这是因此,当我查找两个组件时,我也没有获得两个指定组件和其他组件的集合。

所以主要的问题是如何优化,或者为我想要实现的目标产生更好的查询(或者表结构)?

1 个答案:

答案 0 :(得分:1)

你可以在外面做“HAVING COUNT”:

SELECT `collective_sku_id`
FROM  `sku_sets` 
WHERE `child_sku_id` IN ( 1, 2, 3 ) 
GROUP BY `collective_sku_id`
HAVING COUNT( `collective_sku_id` ) = 3;

然后,为了解决你想要完全匹配child_sku_id的情况,并且没有超过你选择的那个,你可以这样做:

SELECT `collective_sku_id`
FROM  `sku_sets` s
WHERE s.`child_sku_id` IN ( 1, 2) 
AND s.`collective_sku_id` NOT IN 
    (SELECT `collective_sku_id` 
     FROM `sku_sets` ss1
     WHERE ss1.`child_sku_id` NOT IN ( 1, 2) )
GROUP BY `collective_sku_id`
HAVING COUNT( `collective_sku_id` ) = 2;

最后一部分我不知道如果没有NOT IN

你怎么办

编辑:

OP采用的解决方案在评论中:

  

记录原始sku表中的组件数

这使得查询更容易,无需使用子查询。

sqlfiddle demo (更新)