如何对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;
我可能打错了一些字(在我的智能手机上打字),但你已经明白了。
我有一个员工 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;
我可能打错了一些字(在我的智能手机上打字),但你已经明白了。