如何对MySQL中的数字字符串使用比较运算符?

How to use comparison operator for numeric string in MySQL?

我有一个员工 table,他有 VARCHAR 类型的经验,这个字段结合了总年份和总月份,用破折号 (-) 分隔,所以我必须过滤经验year 有3年以上工作经验。

我的table结构:

所以现在我必须获得超过 3 年经验的身份证。 我试过如下,

SELECT * FROM employee WHERE experience LIKE '>=3%';

我知道比较运算符不支持字符串,但我没有任何新的解决方案。有什么解决办法吗?

对于这个简单的案例,strcmp 怎么样?如果你同时需要年和月,它就不会工作。

mysql> select strcmp('3-','3-1');
+--------------------+
| strcmp('3-','3-1') |
+--------------------+
|                 -1 |
+--------------------+
1 row in set (0.00 sec)

mysql> select strcmp('3-','3-9');
+--------------------+
| strcmp('3-','3-9') |
+--------------------+
|                 -1 |
+--------------------+
1 row in set (0.00 sec)

mysql> select strcmp('3-','2-9');
+--------------------+
| strcmp('3-','2-9') |
+--------------------+
|                  1 |
+--------------------+
1 row in set (0.00 sec)

你在这样的查询中使用它:

mysql> select * from main where strcmp('ab', url) = 1;
+----+---------------+
| id | url           |
+----+---------------+
|  1 | a.com         |
|  2 | aa.com        |
|  3 | aaa.com       |
|  4 | aachen.com    |
|  5 | aah.com       |
|  6 | aaliyah.com   |
|  7 | aaliyahs.com  |
|  8 | aardvark.com  |
|  9 | aardvarks.com |
| 10 | aaron.com     |
| 11 | aas.com       |
+----+---------------+
11 rows in set (0.02 sec)

所以在你的情况下你会想要 select * from employee where strcmp('3-', experience) = -1;

如果我是数据库管理员,并且如果提到的 experience 意味着从事这项工作的年数,我会希望我只是使用时间戳作为开始和结束时间,这样就可以很容易地计算出来。否则每个月都有一个批处理作业必须更新该字段。

http://dev.mysql.com/doc/refman/5.7/en/string-comparison-functions.html#function_strcmp

[更新:通过检查字符串的年份部分是否大于单个数字来修复 11 到 29 的情况]

select * from employee where strcmp('3-', experience) = -1 or instr(experience, '-') > 2;

基于转换为数字的更好答案:

select * from employee where cast(substring(experience, 1, instr(experience, '-')-1) as signed) >= 3;

mysql> select cast(substring('11-3', 1, instr('11-3', '-')-1) as signed);
+------------------------------------------------------------+
| cast(substring('11-3', 1, instr('11-3', '-')-1) as signed) |
+------------------------------------------------------------+
|                                                         11 |
+------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select cast(substring('11-3', 1, instr('11-3', '-')-1) as signed) > 3;
+----------------------------------------------------------------+
| cast(substring('11-3', 1, instr('11-3', '-')-1) as signed) > 3 |
+----------------------------------------------------------------+
|                                                              1 |
+----------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select cast(substring('11-3', 1, instr('11-3', '-')-1) as signed) >= 3;
+-----------------------------------------------------------------+
| cast(substring('11-3', 1, instr('11-3', '-')-1) as signed) >= 3 |
+-----------------------------------------------------------------+
|                                                               1 |
+-----------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select cast(substring('3-0', 1, instr('3-0', '-')-1) as signed) >= 3;
+---------------------------------------------------------------+
| cast(substring('3-0', 1, instr('3-0', '-')-1) as signed) >= 3 |
+---------------------------------------------------------------+
|                                                             1 |
+---------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select cast(substring('2-11', 1, instr('2-11', '-')-1) as signed) >= 3;
+-----------------------------------------------------------------+
| cast(substring('2-11', 1, instr('2-11', '-')-1) as signed) >= 3 |
+-----------------------------------------------------------------+
|                                                               0 |
+-----------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select cast(substring('22-11', 1, instr('22-11', '-')-1) as signed) >= 3; 
+-------------------------------------------------------------------+
| cast(substring('22-11', 1, instr('22-11', '-')-1) as signed) >= 3 |
+-------------------------------------------------------------------+
|                                                                 1 |
+-------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select cast(substring('11-0', 1, instr('11-0', '-')-1) as signed) >= 3; 
+-----------------------------------------------------------------+
| cast(substring('11-0', 1, instr('11-0', '-')-1) as signed) >= 3 |
+-----------------------------------------------------------------+
|                                                               1 |
+-----------------------------------------------------------------+
1 row in set (0.00 sec)

unsigned 可能会更好地提高可读性。不太可能对查询产生任何影响。

Select * from main where cast(split_str(experience, '-', 1) as unsigned) >= 3;

split_str(这是一个用户函数:http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/,默认情况下在 mysql 中不存在)将使用其分隔符拆分您的列,并且转换会将您的字符串转换为 int unsigned , 然后你可以测试它。 否则,如果有一天你想测试月份和年份,就像所有超过 3 年 10 个月的经验一样,你可以将你的值转换为十进制(这也适用于上述测试):

Select * from main where cast(replace(experience, '-', '.') As decimal(5,2)) > 3.10;

我可能打错了一些字(在我的智能手机上打字),但你已经明白了。