然后用逗号分隔列,然后显示出现在所有行中的所有值?

时间:2019-06-02 15:50:27

标签: mysql

表格:

enter image description here

输入将是item_id的列表,例如2,3,4,而该输出将是在所有项目中找到的所有store_id ...因此:102,104

另一个示例输入:1,2,输出:102

MySQL是否提供此类操作?

首先,我需要对输入进行选择。然后,我可以将select中的所有store_id放入1个变量中,并找到出现n次(n为输入计数)的所有store_id?

为什么我的问题不同

enter image description here

我不是在问定界列表是好是坏,或者与之相关的任何事情。我在问,如何使用它来获得结果?

2 个答案:

答案 0 :(得分:1)

您基本上是要从查找N个item_id的列表集中找到N个逗号分隔列表的交集。

您存储逗号分隔列表的方式确实使这变得更加困难。

要解决这个难题,我可以想到一种方法:

使用每个store_id创建一个表。

mysql> create table stores (store_id int primary key);

mysql> insert into stores values (101), (102), (103), (104);

现在,基于CSV与stores表中各个值的匹配,您可以将逗号分隔的列表中的store集合转换为许多行。

mysql> select * from mytable as t join stores as s on find_in_set(s.store_id, t.store_id)
  where item_id in (2,3,4);
+---------+-----------------+----------+
| item_id | store_id        | store_id |
+---------+-----------------+----------+
|       3 | 101,102,103,104 |      101 |
|       2 | 102,104         |      102 |
|       3 | 101,102,103,104 |      102 |
|       4 | 102,103,104     |      102 |
|       3 | 101,102,103,104 |      103 |
|       4 | 102,103,104     |      103 |
|       2 | 102,104         |      104 |
|       3 | 101,102,103,104 |      104 |
|       4 | 102,103,104     |      104 |
+---------+-----------------+----------+

然后按store_id对这些行进行分组。假设您要搜索N个item_id,则这些计数为N的组就是符合条件的组。

mysql> select s.store_id, count(*) 
  from mytable as t join stores as s on find_in_set(s.store_id, t.store_id) 
  where item_id in (2,3,4) 
  group by s.store_id;
+----------+----------+
| store_id | count(*) |
+----------+----------+
|      101 |        1 |
|      102 |        3 |
|      103 |        2 |
|      104 |        3 |
+----------+----------+

您可以使用HAVING子句将组过滤为所需的组。

mysql> select s.store_id, count(*) 
  from mytable as t join stores as s on find_in_set(s.store_id, t.store_id)
  where item_id in (2,3,4) 
  group by s.store_id 
  having count(*) = 3;
+----------+----------+
| store_id | count(*) |
+----------+----------+
|      102 |        3 |
|      104 |        3 |
+----------+----------+

此问题不仅在于您需要具有列出所有store_id的另一个表,而且FIND_IN_SET()函数效率低下并且无法通过索引进行优化。它一定要进行交叉联接,这意味着对于X个商品和Y个商店,它将对X个商品进行表格扫描,对于每个商品,它将对Y个商店进行表格扫描。随着您拥有更多的商店和物品,性能将与X * Y成正比。

这就是为什么当您确实需要在字符串中存储与单个ID进行比较的查询时,存储以逗号分隔的ID列表通常不是一个好主意的原因。

您应该拥有的是三个表:

  • 一个项目表
  • 一张商店的桌子
  • 一个表,该表枚举每对商品和商店

示例:

mysql> create table store_has_item (item_id int, store_id int, primary key (item_id, store_id));

每对商品和存储行填充一行:

mysql> insert into store_has_item
    -> select t.item_id, s.store_id from mytable as t join stores as s on find_in_set(s.store_id, t.store_id);
Query OK, 15 rows affected (0.02 sec)
Records: 15  Duplicates: 0  Warnings: 0

现在,您可以仅查询单个表中的N个项目(按store_id分组),然后返回计数为N的那些分组:

mysql> select store_id from store_has_item where item_id in (2,3,4)
  group by store_id having count(*) = 3;
+----------+
| store_id |
+----------+
|      102 |
|      104 |
+----------+

答案 1 :(得分:-1)

  

MySQL是否提供此类操作?

当然,如果我理解正确,您只希望选择每个item_id可能获得的所有商店ID,您可以通过一条简单的语句来实现:

我找不到您的数据库布局,因此您必须根据需要进行处理:

SELECT 
    a.id, /* These id´s are your item_id´s */
    GROUP_CONCAT(b.store_id) as store_ids /* These line puts your store_ids into one output */
FROM item_id a
JOIN store_id b ON b.item_id = a.id 
GROUP BY item_id

此语句返回如下内容:

+ --------------- + ---------------------- +
| item_id | store_ids |
+ ----------- + ---------------------- +
| 1 | 120,210,330 |
| 2 | 90,10,30 |
| 3 | 70,120,90,330 |
+ ----------- + ---------------------- +

格里兹毒素