需求
在一个数据库表中有一个字段中的数据是通过特殊符号进行分隔的,现需要统计分隔符分开的各数据的条数。
数据准备
-- ----------------------------
-- 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对拆分的数据进行统计。
三种方式,相同的原理
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;
-- ----------------------------
-- 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;
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;
执行结果:
已有表可以是自身,也可是数据库中已有表(可以不是序列表),行数必须大于分割字段的最大逗号数。
总结