MySQL 使用查找将 2 个逗号分隔的列拆分为多行

MySQL Split 2 comma separated columns into multiple rows with lookup

我有一个 table,其中 两个 列的值由逗号分隔,另一个 table类别。 group_1 最多可以有 30 个分隔值,group_2 最多可以有 5 个分隔值

myProducts

alias group_1 group_2
product_a 1,2,3,[...] uk, us [...]
product_b 2,4,[...] uk, us, [...]
product_c 1,4,[...] spain, germany, [...]

myCategories

id category
1 category_a
2 category_b
3 category_c
4 category_d

是否可以使用 MySQL 将逗号分隔的字段拆分为多行和 return 从类别 table 中查找值后的结果。所以在上面的示例中,原始 table 的第一行将 return:

alias group_1 group_2
product_a category_a uk
product_a category_a us
product_a category_b uk
product_a category_b us
product_a category_c uk
product_a category_c us
... ... ...

查找部分是我想要的,但如果它被证明太复杂,我可以没有那个部分。

是的,但您不会对性能满意。

您可以使用 MySQL 的 FIND_IN_SET() 函数将逗号分隔的列表与单个值进行匹配。

select p.alias, a.category as group_1, c.country as group_2 
from myProducts p join myCategories a on find_in_set(a.id, p.group_1) 
join countries c on find_in_set(c.country, p.group_2);

+-----------+------------+---------+
| alias     | group_1    | group_2 |
+-----------+------------+---------+
| product_c | category_a | spain   |
| product_c | category_d | spain   |
| product_a | category_a | uk      |
| product_a | category_b | uk      |
| product_b | category_b | uk      |
| product_a | category_c | uk      |
| product_b | category_d | uk      |
+-----------+------------+---------+

我确实创建了另一个查找 table countries:

create table countries (country varchar(20) primary key);
insert into countries values ('uk'),('us'),('spain'),('germany');

注意:如果以逗号分隔的列表有空格,它们将被视为列表中每个字符串的一部分,因此您要删除空格。

select p.alias, a.category as group_1, c.country as group_2 
from myProducts p join myCategories a on find_in_set(a.id, p.group_1) 
join countries c on find_in_set(c.country, replace(p.group_2,' ',''));

+-----------+------------+---------+
| alias     | group_1    | group_2 |
+-----------+------------+---------+
| product_c | category_a | germany |
| product_c | category_d | germany |
| product_c | category_a | spain   |
| product_c | category_d | spain   |
| product_a | category_a | uk      |
| product_a | category_b | uk      |
| product_b | category_b | uk      |
| product_a | category_c | uk      |
| product_b | category_d | uk      |
| product_b | category_b | us      |
| product_b | category_d | us      |
+-----------+------------+---------+

但是如果你这样做,就没有办法优化索引查找。所以每个连接都将是一个 table 扫描。随着 table 变大,您会发现性能下降到无法使用的程度。

对此进行优化的方法是避免使用逗号分隔的列表。将多对多关系规范化为新的 table。然后查找可以使用索引,除了 all the other problems with using comma-separated lists.

之外,您将避免性能下降

回复您的评论:

您可以通过明确列出国家/地区来创建派生 table:

FROM ...
JOIN (
  SELECT 'us' AS country UNION SELECT 'uk' UNION SELECT 'spain' UNION SELECT 'germany'
) AS c

但这越来越荒谬了。您没有使用 SQL 来获得任何优势。您不妨将整个数据集取回您的客户端应用程序,并将其分类为内存中的某些数据结构。