如何仅选择一个特定的集合,该特定的集合包括mySQL

时间:2019-02-18 19:45:07

标签: mysql

我正在尝试从包含数字列表的mySQL表中提取特定行。

我有一个包含2列ID和数据的表格。每行都有一个排序的,用逗号分隔的数字记录,范围从1到1000。我只想选择其中包含部分或全部特定数字集的记录。我已经尝试过使用LIKE和IN,还查看了FIND_IN_SET。

t1.id       t1.data
1          2,9,569
2          2,9,991,979
3          9,569,763
4          52,57,569,763,892,897
5          763
6          2,9,10,15,151,569,771,801,888,973

如果我要查找具有一个或多个值(2,9,569,763)的行,则无需编写:

SELECT t1.id from t1
WHERE t1.data NOT IN (1,3,4,5,6,7,8,10,11,...........,1000);

返回3行,t1.id = 1,3和5。

有没有更简单的方法?类似于(在mySQL中):

SELECT t1.id from t1
WHERE t1.data "only includes one or more of" (2,9,569,763);

3 个答案:

答案 0 :(得分:1)

不简单,但是..

对单个匹配进行计数,并将其与data列中所有值的数量进行比较。它们必须相等。

select id, data
from t1
where (find_in_set(2, data) > 0)
    + (find_in_set(9, data) > 0)
    + (find_in_set(569, data) > 0)
    + (find_in_set(763, data) > 0)
    = char_length(data) - char_length(replace(data, ',', '')) + 1

演示:https://www.db-fiddle.com/f/oLcrz4vmXRWXqYQhCnZA5z/0

答案 1 :(得分:1)

Paul Spiegel的答案给出了正确的结果,但是由于使用了FIND_IN_SET(),因此无法使用索引进行优化。它将始终进行表扫描,当您拥有更多的行时,它将变得越来越昂贵。

您应该以此为线索,当您实际上想对列表的离散成员进行一些搜索时,将数字列表作为逗号分隔的列表存储在字符串列中是个坏主意。

您应该做的是将列表存储为子表,每行一个成员。

CREATE TABLE mydata (
  t1id INT NOT NULL,
  member INT NOT NULL,
  PRIMARY KEY (t1id, member),
  FOREIGN KEY (t1id) REFERENCES t1(id)
);

INSERT INTO mydata VALUES
(1,2),(1,9),(1,569),
(2,2),(2,9),(2,991),(2,979),
(3,9),(3,569),(3,763),
(4,52,(4,57,(4,569,(4,763,(4,892),(4,897),
(5,763),
(6,2),(6,9),(6,10),(6,15),(6,151),(6,569),(6,771),(6,801),(6,888),(6,973);

现在,您将把原始表t1联接到mydata,但排除与所需列表中值匹配的项。

mysql> select * from t1 left join mydata on t1.id=mydata.t1id 
    and mydata.member not in (2,9,569,763);
+----+------+--------+
| id | t1id | member |
+----+------+--------+
|  1 | NULL |   NULL |
|  2 |    2 |    979 |
|  2 |    2 |    991 |
|  3 | NULL |   NULL |
|  4 |    4 |     52 |
|  4 |    4 |     57 |
|  4 |    4 |    892 |
|  4 |    4 |    897 |
|  5 | NULL |   NULL |
|  6 |    6 |     10 |
|  6 |    6 |     15 |
|  6 |    6 |    151 |
|  6 |    6 |    771 |
|  6 |    6 |    801 |
|  6 |    6 |    888 |
|  6 |    6 |    973 |
+----+------+--------+

您会看到id为1、3、5的NULL,因为没有任何不在指定列表中的值。这些是您要返回的ID。

mysql> select t1.id from t1 left join mydata on t1.id=mydata.t1id 
    and mydata.member not in (2,9,569,763) 
  where mydata.member is null;
+----+
| id |
+----+
|  1 |
|  3 |
|  5 |
+----+

答案 2 :(得分:0)

尝试使用REGEXP函数:

SELECT t1.id from t1
WHERE t1.data REGEXP '(2,9,569,763)';