1

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

  • 电路板
  • 引领
  • 电池连接器

现在我可以单独出售这些物品,或者我可以将它们作为最终物品出售,即我在发布它们之前将它们焊接在一起。(这只是一个插图,所以请不要评论说让人们自己将它们焊接在一起)。

但是,使用 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

这张表现在让我可以找出sku4,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出现了 3 次(这就是当我寻找两个组件时,我也没有得到两个指定组件和其他组件的集合)。

所以主要问题是我如何优化或生成更好的查询(或者可能是表结构)来实现我想要在上面实现的目标?

4

1 回答 1

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 (更新)

于 2013-10-18T15:23:36.793 回答