2

我们在 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。

4

3 回答 3

4

使用第三个表:

Product_Option_Assoc (product_id, option_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);
于 2012-12-14T11:45:27.713 回答
0

使用FIND_IN_SET(str,strlist)可以解决问题吗?

我不确定它的效率,但会给您一种简单的方法来搜索具有特定选项的产品。

于 2012-12-14T11:46:58.617 回答
0

通过将选项列表转换为单个字符串,您将失去数据库的所有功能并强迫自己使用字符串匹配和其他组合。使用链接表。这是正确的方式。然后弄清楚如何为它编写查询。

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在我看来,查询更清楚地传达了这个想法。

于 2012-12-14T13:17:39.443 回答