没有简单的本机函数来检查数值(例如 1017)是否在存储为字符串的一组范围内,如您所示。
简短的回答是,不,这种搜索不能在 MySQL 中完成。
更长的答案是,尽管不切实际,但可以执行所需的字符串操作,以提取该列表中每个范围的单个最小和最大分量。
首先,从性能的角度来看,这是不切实际的(您不想为每次搜索都做那种繁重的工作。其次,由于执行这种字符串操作需要扭曲的 SQL,这是不切实际的。
从 MySQL 性能的角度来看,执行此类搜索的更好方法是将范围列表表示为表中的单独行。
r_mod r_min r_max
----- ----- -----
0 1002 1004
1 1101 1105
0 1102 1104
1 1201 1205
要让 MySQL 将这些范围列表中的每一个“拆分”为单独行上的一个范围,每个列表上都有一个尾随分号,您可以执行如下查询:
SELECT n.i
, SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(d.foo,';', n.i ),';',-1),'-', 1 ),'-',-1)%2 AS r_mod
, SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(d.foo,';', n.i ),';',-1),'-', 1 ),'-',-1)/1 AS r_min
, SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(d.foo,';', n.i ),';',-1),'-', 2 ),'-',-1)/1 AS r_max
FROM (SELECT '1002-1004;1101-1105;1102-1104;1201-1205;1202-1204;1301-1305;' AS foo) d
CROSS
JOIN ( SELECT h.d*100+t.d*10+o.d+1 AS i
FROM (SELECT 0 AS d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) o
CROSS
JOIN (SELECT 0 AS d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t
CROSS
JOIN (SELECT 0 AS d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) h
) n
HAVING r_max > 0
(请注意,对于该查询,范围列表字符串必须附加一个尾随分号,并且该查询只会提取每个列表的前 1000 个条目。)鉴于这种结构,理论上可以使用数值比较:
avalue MOD 2 = r_mod AND avalue BETWEEN r_min AND r_max
再次回到较短的答案,将范围存储在表格中作为范围的字符串列表,对每次搜索进行这种类型的字符串操作是不切实际的。
使用带有单独行的预填充表,其中每个 r_min 和 r_max 值,可以在 MySQL 中进行搜索。