MySQL 对 IP 字段的排序问题
MySQL 对 IP 字段的排序问题
问题描述
想对一张带有 IP 字段的表,对 IP 字段进行升序排序,方便查看每个段的 IP 信息。
表结构和表数据如下:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for t_ip
-- ----------------------------
DROP TABLE IF EXISTS `t_ip`;
CREATE TABLE `t_ip` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ip` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of t_ip
-- ----------------------------
INSERT INTO `t_ip` VALUES (1, '192.168.10.8');
INSERT INTO `t_ip` VALUES (2, '192.168.10.9');
INSERT INTO `t_ip` VALUES (3, '192.168.10.10');
INSERT INTO `t_ip` VALUES (4, '192.168.10.1');
INSERT INTO `t_ip` VALUES (5, '192.168.8.8');
INSERT INTO `t_ip` VALUES (6, '192.167.10.8');
INSERT INTO `t_ip` VALUES (7, '192.167.8.8');
INSERT INTO `t_ip` VALUES (8, '92.168.10.8');
INSERT INTO `t_ip` VALUES (9, '92.68.10.8'); SET FOREIGN_KEY_CHECKS = 1;
数据库查询截图如下:

如果按照 IP 字段升序,查询效果如下:

问题原因
由于 IP 字段是varchar 类型,MySQL在进行排序的时候,并不会将 IP中的 “192”和“92” 自动识别为数字进行处理,而是作为字符串处理了。
因此,会查询到的结果达不到预期。
问题解决
如果想要将92开头的IP,排在192开头的之前,并且每个. 分隔的段都要保持数字上的升序,需要对 IP 字段按照 . 进行分解为4段,逐次排序处理。
处理 SQL 如下:
select ip from t_ip
ORDER BY
CONVERT(SUBSTRING_INDEX(ip, '.', 1), SIGNED),
CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 2), '.', -1), SIGNED),
CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(ip, '.', 3), '.', -1), SIGNED),
CONVERT(SUBSTRING_INDEX(ip, '.', -1), SIGNED);
处理后的效果截图如下(此时已经达到了预期的排序效果):

【说明】
此处用到了MySQL的两个库函数:
1) CONVERT(expr,type): 此函数的作用是将表达式转换为特定类型
如:上面用到的 CONVERT(SUBSTRING_INDEX(ip, '.', 1), SIGNED) 是将ip字段中获取的第一位,转换为整数。
2)SUBSTRING_INDEX(str,delim,count):此函数的作用是将一个字段串,按照某个标识字符串截取,并获取第几个之前
如:SUBSTRING_INDEX(ip, '.', 1) 是将IP按照 '.' 分隔,获取第一位。如果是ip是 192.168.10.8,获取的就是 192
SUBSTRING_INDEX(ip, '.', -1) 是将IP按照 '.' 分隔,获取最后一位。如果是ip是 192.168.10.8,获取的就是 8
额外补充
如果IP字段中存在多IP,如:192.168.10.2,194.16.12.123,要求排序的时候,按照逗号前的第一个IP参与排序。需要如何实现呢?
如果还是按照上面的SQL,发现不能适配该场景,效果如下:

此时,需要对多IP的场景的逗号稍微处理下即可,处理SQL如下:
select ip from t_ip
ORDER BY
CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(ip, ',', 1), '.', 1), SIGNED),
CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(ip, ',', 1), '.', 2), '.', -1), SIGNED),
CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(ip, ',', 1), '.', 3), '.', -1), SIGNED),
CONVERT(SUBSTRING_INDEX(SUBSTRING_INDEX(ip, ',', 1), '.', -1), SIGNED);
该SQL的查询效果如下:

MySQL 对 IP 字段的排序问题的更多相关文章
- Mysql hql字符串字段中是否包含某个字符串,用 find_in_set
有这样一个需求,在Mysql数据库字符串字段(权限)中,有范围在 1 到 N 之间代表不同权限的值,分别被','分开,现在要取出具有某权限的所有成员列表. 创建表: 1 CREATE TABLE us ...
- MySQL 表与字段编码格式报错
MySQL 表与字段编码格式报错 一.数据库,表,字段编码格式都为latin1(iso-8859-1) .当数据保存到数据库后,中文显示乱码. 解决办法: 1.在访问数据库连接串中添加编码格式: &l ...
- paip.解决 数据库mysql增加列 字段很慢添加字段很慢
paip.解决 数据库mysql增加列 字段很慢添加字段很慢 #环境如下: mysql5.6 数据仅仅3w alter table xxx add column yyy int default ...
- MYSQL的分区字段,必须包含在主键字段内
MYSQL的分区字段,必须包含在主键字段内 MYSQL的分区字段,必须包含在主键字段内 在对表进行分区时,如果分区字段没有包含在主键字段内,如表A的主键为ID,分区字段为createtime ,按 ...
- mysql中判断字段为空
mysql中判断字段为null或者不为null 在mysql中,查询某字段为空时,切记不可用 = null, 而是 is null,不为空则是 is not null select nulco ...
- MySQL根据某个字段查询重复的数据
select count(*) '个数',mobile '手机号',`name` '用户名' from users group by mobile having(count(*) > 1); = ...
- Sender IP字段为"0.0.0.0"的ARP请求报文
今天在研究免费ARP的过程中,抓到了一种Sender IP字段为“0.0.0.0”的ARP请求报文(广播),抓包截图如下: 这让我很疑惑.一个正常的ARP请求不应该只是Target MAC字段为全0吗 ...
- awk中截取IP字段
由于文本的特殊性,IP字段可能并不是在特定的字段中. 借助awk的match()函数进行匹配截取 awk --re-interval '($0 ~ "xxx"){match($0, ...
- 【mysql】IP地址整数int和varchar的转换
mysql中IP地址的存储 IP:如192.168.12.145,在存储时,若是采用varchar进行存储,存在两个主要缺点: 存储空间占用较大: 查询检索较慢: 解决方式: 存储时:将字符串类型的I ...
随机推荐
- PLSQL功能一览(1/2)
用了Oracle几年了,除了PLSQL几乎就没用过别的工具.临时起义想看看PLSQL有哪些功能是我平时没注意的,别是一直有好办法,我却用着笨办法. 本文针对PLSQL12.0.7 1.登录以后使用My ...
- php正则表达式提取数字,字符串中提取数字
<?php $str = "请注意:有谁知道30901.5号路怎么走?这个因为我买了100块的烧饼和7901的钥匙了,那个对了,我再拿个30000"; $pattern = ...
- AngularJS实现数据列表的增加、删除和上移下移等功能实例
转: http://www.jb51.net/article/91991.htm 这篇文章给大家分享了AngularJS循环实现数据列表的增加.删除和上移下移等基础功能,对大家学习AngularJ ...
- QT对话框
QFileDialog:文件对话框 QString fileName=QFileDialog::getOpenFileName(this,"打开文件", "/" ...
- XMLHttpRequest status为0
//创建XMLHttpRequest()对象 var request = new XMLHttpRequest(); ...... 今天写一个ajax , 明明是有结果返回的,但得到的request ...
- 《Python基础教程》第一章:基础知识
如果希望只执行普通的除法,可以在程序前加上以下语句:from __future__ import division.还有另外一个方法,如果通过命令行运行Python, 可以使用命令开关-Qnew.此时 ...
- 【技巧 二进制分组】bzoj4398: 福慧双修&&2407: 探险
二进制分组也可以说是一种比较优美的拆贡献方式吧? Description 菩萨为行,福慧双修,智人得果,不忘其本.——唐朠立<大慈恩寺三藏法师传>有才而知进退,福慧双修,这才难得.——乌雅 ...
- mysqldump 使用--tab=path参数时提示mysqldump: Got error: 1290: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement when executing 'SELECT INTO OUTFILE'
报错: [root@zedu test]# mysqldump -h127.0.0.1 -uroot -p --single-transaction --add-drop-database --tab ...
- 通过CSS实现 文字渐变色 的两种方式
说明 这次的重点就在于两个属性, background 属性 mask 属性这两个属性分别是两种实现方式的关键. 方式一 解释 <!DOCTYPE html> <html> & ...
- printf格式输出
参考:http://www.cplusplus.com/reference/cstdio/printf/ C string that contains the text to be written t ...