简体   繁体   English

MySQL-用一组数字的所有组合查找带有逗号分隔值的字段

[英]MySQL - find field with comma separated value by all combinations of a set of numbers

We have a product table in MySQL where each row has a field with a comma separated value of options wich combine to become this product. 我们在MySQL中有一个产品表,其中的每一行都有一个字段,其中用逗号分隔的选项值可以组合成该产品。 In the scheme below you can see both tables. 在下面的方案中,您可以看到两个表。 The field with comma separated values is option_ids, this can for example look like 2,5,6,23 or 4,2,76. 逗号分隔值的字段是option_ids,例如,可以看起来像2,5,6,23或4,2,76。 These numbers are options wich exist in the option table. 这些数字是存在于选项表中的选项。

Product: 产品:
|product_id|name|description|option_ids|price|

Option: 选项:
|option_id|type_id|label|group|pos|count|price|

The input we get is an array of unique options. 我们得到的输入是一组唯一的选项。 We wanna find every product that has this set of options or a subset of it in option_ids. 我们想在option_ids中找到所有具有此选项集或其子集的产品。

The way we do this now is by generating a powerset of the array of options so that we have all possible combinations of the array of options. 现在,我们的方法是生成选项数组的幂集,以便我们拥有选项数组的所有可能组合。 Then we generate a mysql query wich queries for all these combinations in 'OR WHERE' statements. 然后,我们在“ OR WHERE”语句中生成一个对所有这些组合进行查询的mysql查询。

The problem here is that the powerset grows exponentially, so when we have an array of 16 unique options the powerset gives an array of 65536 possibilities. 这里的问题是幂集呈指数增长,所以当我们有16个唯一选项的数组时,幂集提供了65536种可能性。 We had to increase the memory usage of php for this to work properly but now we run into MySQL problems because the query gets so enormous. 为了正常工作,我们不得不增加php的内存使用率,但是现在由于查询变得如此庞大而遇到了MySQL问题。

Is there another way to tackle this problem? 有没有其他方法可以解决这个问题?

I hope I've given enough information, if not please do ask! 希望我提供了足够的信息,如果没有,请务必提出!

EDIT: A third table will get us the same problem because we need to find subsets to... It's not said that an array of options IS ONE product, it can be one product but it can also be 2 or 3 products. 编辑:第三张表会给我们带来同样的问题,因为我们需要找到以下子集...不是说选项阵列是一个产品,它可以是一个产品,但也可以是2或3个产品。 For example: options 1,2 make product A, options 2,3 make product B, and options 4,5,6 make product C. If we have option array [1,2,4,5,6] we would want to find product A and C. 例如:选项1,2使产品A,选项2,3使产品B,选项4,5,6使产品C。如果我们有选项数组[1,2,4,5,6],我们希望查找产品A和C。

Use a third table: 使用第三张表:

Product_Option_Assoc ( product_id, option_id ) Product_Option_Assoc(product_id,option_id)

For every option that a product should have, insert a row into that table. 对于产品应具有的每个选项,请在该表中插入一行。 This gives you a real One-to-many relationship between products and options. 这为您提供了产品和选件之间真正的一对多关系。 The number of options can easily vary and it's easy to query for pulling data and updating (no comma parsing required). 选项的数量可以轻松变化,并且很容易查询以提取数据和进行更新(无需逗号解析)。

Example query: get products that have given options associated: 查询示例:获取具有相关选项的产品:

$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);

Would using FIND_IN_SET(str,strlist) do the trick? 使用FIND_IN_SET(str,strlist)会成功吗?

I'm not sure about the efficiency of it but would give you an easy way for searching for products with specific options. 我不确定它的效率,但是会为您提供一种搜索具有特定选项的产品的简便方法。

By turning the option list into a single string, you're losing all the power of databases and forcing yourselves to use string matching and other kludges. 通过将选项列表转换为单个字符串,您将失去数据库的所有功能,并迫使自己使用字符串匹配和其他冲突。 Use a link table. 使用链接表。 It's The Right Way. 这是正确的方式。 Then figure out how to write queries for it. 然后找出如何编写查询。

Product_option ( product_id, option_id )

This is what you say you want: 这就是您要说的:

example: options 1,2 make product A, options 2,3 make product B, and options 4,5,6 make product C. If we have option array [1,2,4,5,6] we would want to find product A and C. 例如:选项1,2使产品A,选项2,3使产品B,选项4,5,6使产品C。如果我们有选项数组[1,2,4,5,6],我们将要查找产品A和C。

To rephrase, you want to retrieve all products that do not have an option that's not in your query array. 要改写,要检索没有这不是你的查询阵列中的一个选项的所有产品。 Here's how to do it: 方法如下:

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)
    )

You could do this explicitly with a join, but an EXISTS query gets the idea across more clearly in my opinion. 您可以通过EXISTS显式地执行此操作,但是我认为EXISTS查询可以更清楚地了解该想法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM