我们在 MySQL 中有一个产品表,其中每一行都有一个字段,其中包含用逗号分隔的选项值,这些选项组合起来成为该产品。在下面的方案中,您可以看到两个表。以逗号分隔值的字段是 option_ids,例如,它可能类似于 2,5,6,23 或 4,2,76。这些数字是选项表中存在的选项。
产品:
|product_id|name|description|option_ids|price|
选项:
|option_id|type_id|label|group|pos|count|price|
我们得到的输入是一系列独特的选项。我们希望在 option_ids 中找到具有这组选项或其子集的每个产品。
我们现在这样做的方法是生成选项数组的幂集,以便我们拥有选项数组的所有可能组合。然后我们生成一个 MySQL 查询,该查询在“OR WHERE”语句中查询所有这些组合。
这里的问题是幂集呈指数增长,因此当我们有 16 个唯一选项的数组时,幂集给出了 65536 种可能性的数组。我们必须增加 PHP 的内存使用量才能正常工作,但现在我们遇到了 MySQL 问题,因为查询变得如此巨大。
还有其他方法可以解决这个问题吗?
我希望我已经提供了足够的信息,如果没有,请询问!
编辑: 第三个表也会给我们带来同样的问题,因为我们需要找到子集......这并不是说一系列选项是一个产品,它可以是一个产品,但也可以是 2 或 3 个产品。例如:选项 1,2 生成产品 A,选项 2,3 生成产品 B,选项 4,5,6 生成产品 C。如果我们有选项数组 [1,2,4,5,6],我们希望找到产品 A 和 C。
使用第三个表:
产品_选项_关联(产品_id,选项_id)
对于产品应具有的每个选项,在该表中插入一行。这为您提供了产品和选项之间真正的“一对多”关系。选项的数量可以很容易地变化,并且很容易查询以提取数据和更新(不需要逗号解析)。
示例查询:获取具有给定关联选项的产品:
$options = array(1, 55, 23); // hard coded but could come from a form (remember to validate/cast as ints)
$optionCommaList = implode(',', $options);
SELECT
p.name
FROM
Product_Option_Assoc a
LEFT JOIN
Products p ON p.product_id = a.product_id
WHERE
a.option_id IN ($optionCommaList);
Product_option ( product_id, option_id )
这就是你所说的你想要的:
示例:选项 1,2 生成产品 A,选项 2,3 生成产品 B,选项 4,5,6 生成产品 C。如果我们有选项数组 [1,2,4,5,6],我们希望找到产品 A 和 C。
换句话说,您想要检索所有“不”具有不在查询数组中的选项的产品。操作方法如下:
SELECT * from Product WHERE NOT EXISTS (
SELECT product_id id, option_id opt from Product_option
WHERE id = Product.product_id AND opt NOT IN (1, 2, 4, 5, 6)
)
您可以通过连接显式地执行此操作,但在我看来,
EXISTS
查询可以更清楚地表达想法。