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的查詢效果如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM