mysql数据库使用sql对特殊分隔符分隔的字段进行统计

需求

在一个数据库表中有一个字段中的数据是通过特殊符号进行分隔的,现需要统计分隔符分开的各数据的条数。

数据准备

-- ----------------------------
-- Table structure for persons
-- ----------------------------
DROP TABLE IF EXISTS `persons`;
CREATE TABLE `persons`  (
  `id` int(0) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名',
  `age` int(0) NULL DEFAULT NULL COMMENT '年龄',
  `sex` varchar(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '性别',
  `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '住址',
  `sect` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '门派',
  `skill` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '绝技,以逗号分隔',
  `power` int(0) NULL DEFAULT NULL COMMENT '战力值',
  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `modify_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 451 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of persons
-- ----------------------------
INSERT INTO `persons` VALUES (427, '张无忌', 16, '男', '昆仑山光明顶', '明教', '九阳神功,太极功,七伤拳,乾坤大挪移', 99, '2021-11-26 16:29:38', '2021-11-26 16:29:38');
INSERT INTO `persons` VALUES (428, '赵敏', 13, '女', '大都', '朝廷', '杂门武功', 30, '2021-11-26 16:32:15', '2021-11-26 16:32:15');
INSERT INTO `persons` VALUES (429, '周芷若', 13, '女', '峨眉山', '峨嵋派', '九阴真经,峨嵋剑法', 80, '2021-11-26 16:32:40', '2021-11-26 16:32:40');
INSERT INTO `persons` VALUES (430, '小昭', 12, '女', '昆仑山光明顶', '明教', '乾坤大挪移', 40, '2021-11-26 16:33:27', '2021-11-26 16:33:27');
INSERT INTO `persons` VALUES (431, '殷离', 12, '女', '峨眉山', '天鹰教', '千蛛万毒手', 50, '2021-11-26 16:36:12', '2021-11-26 16:36:12');
INSERT INTO `persons` VALUES (432, '杨逍', 30, '男', '昆仑山光明顶', '明教', '乾坤大挪移', 80, '2021-11-26 17:12:10', '2021-11-26 17:12:10');
INSERT INTO `persons` VALUES (433, '范遥', 29, '男', '昆仑山光明顶', '明教', '吸星大法', 79, '2021-11-26 17:14:03', '2021-11-26 17:14:03');
INSERT INTO `persons` VALUES (434, '谢逊', 31, '男', '冰火岛', '明教', '七伤拳', 79, '2021-11-26 17:15:40', '2021-11-26 17:15:40');
INSERT INTO `persons` VALUES (435, '殷天正', 40, '男', '峨眉山', '天鹰教', '鹰爪擒拿手', 75, '2021-11-26 17:16:49', '2021-11-26 17:16:49');
INSERT INTO `persons` VALUES (436, '黛绮丝', 35, '女', '灵蛇岛', '明教', '波斯武学', 72, '2021-11-26 17:18:48', '2021-11-26 17:18:48');
INSERT INTO `persons` VALUES (437, '韦一笑', 40, '男', '昆仑山光明顶', '明教', '寒冰绵掌', 68, '2021-11-26 17:19:45', '2021-11-26 17:19:45');
INSERT INTO `persons` VALUES (438, '宋远桥', 41, '男', '武当山', '武当派', '太极功', 78, '2021-11-26 17:23:47', '2021-11-26 17:23:47');
INSERT INTO `persons` VALUES (439, '俞莲舟', 39, '男', '武当山', '武当派', '太极功', 75, '2021-11-26 17:24:29', '2021-11-26 17:24:29');
INSERT INTO `persons` VALUES (440, '俞岱岩', 38, '男', '武当山', '武当派', '太极功', 75, '2021-11-26 17:24:55', '2021-11-26 17:24:55');
INSERT INTO `persons` VALUES (441, '张松溪', 37, '男', '武当山', '武当派', '太极功', 75, '2021-11-26 17:25:41', '2021-11-26 17:25:41');
INSERT INTO `persons` VALUES (442, '张翠山', 36, '男', '冰火岛', '武当派', '太极功', 77, '2021-11-26 17:26:10', '2021-11-26 17:26:10');
INSERT INTO `persons` VALUES (443, '殷梨亭', 33, '男', '武当山', '武当派', '太极功', 76, '2021-11-26 17:26:37', '2021-11-26 17:26:37');
INSERT INTO `persons` VALUES (444, '莫声谷', 30, '男', '武当山', '武当派', '太极功', 70, '2021-11-26 17:27:03', '2021-11-26 17:27:03');
INSERT INTO `persons` VALUES (445, '空见', 50, '男', '少林寺', '少林派', '少林龙爪手', 80, '2021-11-26 17:29:06', '2021-11-26 17:29:06');
INSERT INTO `persons` VALUES (446, '空闻', 49, '男', '少林寺', '少林派', '大力金刚指', 80, '2021-11-26 17:30:00', '2021-11-26 17:30:00');
INSERT INTO `persons` VALUES (447, '空智', 47, '男', '少林寺', '少林派', '少林九阳功', 82, '2021-11-26 17:30:56', '2021-11-26 17:30:56');
INSERT INTO `persons` VALUES (448, '空性', 45, '男', '少林寺', '少林派', '少林七十二绝技', 78, '2021-11-26 17:31:57', '2021-11-26 17:31:57');
INSERT INTO `persons` VALUES (449, '殷素素', 33, '女', '冰火岛', '天鹰教', '杂学', 65, '2021-11-26 17:32:53', '2021-11-26 17:32:53');
INSERT INTO `persons` VALUES (450, '灭绝师太', 33, '女', '峨眉山', '峨嵋派', '峨嵋剑法', 80, '2021-11-26 17:33:41', '2021-11-26 17:33:41');

 现需统计各个绝技的人数☺

思路

使用sql根据逗号将一行数据拆分成多行数据 ,然后使用group by对拆分的数据进行统计。

三种方式,相同的原理

  1. 使用MySQL库中的自增序列表
     
    SELECT
    SUBSTRING_INDEX(SUBSTRING_INDEX(p.skill, ',', temp.help_topic_id + 1), ',' , -1) AS unique_skill,
    COUNT(p.id) AS count
    FROM persons AS p
    JOIN mysql.help_topic AS temp ON temp.help_topic_id < (LENGTH(p.skill) - LENGTH(REPLACE (p.skill, ',', '')) + 1)
    GROUP BY unique_skill
    ORDER BY count DESC;

    执行结果:

    mysql数据库使用sql对特殊分隔符分隔的字段进行统计_第1张图片

  2. 自建自增序列表

    创建自增表并添加数据
     
    -- ----------------------------
    -- Records of sys_incre_table
    -- ----------------------------
    CREATE TABLE `sys_incre_table` (
      `auto_incre_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用于循环的自增表',
      PRIMARY KEY (`auto_incre_id`) USING BTREE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    -- ----------------------------
    -- Records of sys_incre_table
    -- ----------------------------
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (0);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (1);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (2);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (3);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (4);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (5);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (6);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (7);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (8);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (9);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (10);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (11);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (12);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (13);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (14);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (15);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (16);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (17);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (18);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (19);
    INSERT INTO `my_test`.`sys_incre_table`(`auto_incre_id`) VALUES (20);
    SUBSTRING_INDEX(SUBSTRING_INDEX(p.skill, ',', temp.auto_incre_id + 1), ',' , -1) AS unique_skill,
    COUNT(p.id) AS count
    FROM persons AS p
    JOIN sys_incre_table AS temp ON temp.auto_incre_id < (LENGTH(p.skill) - LENGTH(REPLACE (p.skill, ',', '')) + 1)
    GROUP BY unique_skill
    ORDER BY count DESC;

    执行结果:

    mysql数据库使用sql对特殊分隔符分隔的字段进行统计_第2张图片

  3. 以数据库里已有表,构建自增序列表
SELECT 
SUBSTRING_INDEX(SUBSTRING_INDEX(p.skill, ',', temp.id + 1), ',', -1) AS unique_skill,
COUNT(p.id) AS count
FROM persons AS p
JOIN (SELECT (@ROW := @Row + 1) AS id FROM persons AS p, (SELECT @Row := -1) AS temp LIMIT 20) temp ON temp.id < (LENGTH(p.skill) - LENGTH(REPLACE(p.skill, ',', '')) + 1)
GROUP BY unique_skill
ORDER BY count DESC;

执行结果:

mysql数据库使用sql对特殊分隔符分隔的字段进行统计_第3张图片已有表可以是自身,也可是数据库中已有表(可以不是序列表),行数必须大于分割字段的最大逗号数。

总结

  1. 序列表必须从0开始,行数与最长逗号有关,行数至少比最长逗号个数加1,可以建0~1000。
  2. 为什么不推荐使用MySQL自带的自增序列表mysql.help_topic?因为好多公司的数据库是没有权限操作这些表的, 不能使用。

 

你可能感兴趣的:(#,数据库,数据库,sql,mysql)