现在数据库中有一个字段含有多个名字,然后要做统计,实在想不出怎么写sql语句
比如table1中有两个个字段叫class和pass
class里面记录了课程,pass里面记录了所有通过该class的学生比如:
class pass
1 张三;李四;王麻子
2 黎明;刘德华;张学友
3 张三;张学友
. .....
. .....
现在要统计,通过课程最多的前5个,应该怎么写啊pass里面的人使用分号隔开的,有几个难点,感觉,首先对每一条记录里的pass字段,怎么用;将其分割,其次每个记录里pass里的;的个数是不一样的,好难啊,感觉,能实现吗
比如table1中有两个个字段叫class和pass
class里面记录了课程,pass里面记录了所有通过该class的学生比如:
class pass
1 张三;李四;王麻子
2 黎明;刘德华;张学友
3 张三;张学友
. .....
. .....
现在要统计,通过课程最多的前5个,应该怎么写啊pass里面的人使用分号隔开的,有几个难点,感觉,首先对每一条记录里的pass字段,怎么用;将其分割,其次每个记录里pass里的;的个数是不一样的,好难啊,感觉,能实现吗
下面可能是你要的结果 分组统计每人完成课程数自己写create table test2 (calss NUMERIC,pass CHAR (100) );
insert into test2 values(1,'张三;李四;王麻子');
insert into test2 values(2,'黎明;刘德华;张学友');
insert into test2 values (3,'张三;张学友');create table test2_name(id INT(8) NOT NULL AUTO_INCREMENT, PRIMARY KEY(`id`),name char(20));
insert into test2_name (name) values ('张三');
insert into test2_name (name) values ('李四');
insert into test2_name (name) values ('王麻子');
insert into test2_name (name) values ('黎明');
insert into test2_name (name) values ('刘德华');
insert into test2_name (name) values ('张学友');select t.calss,n.name from test2 t inner join test2_name n on instr( t.pass,n.name)>0
这个只是统计了每一条记录相应字段里姓名的个数,并没有得到我想要的结果最后一段 order 一下不就结了?select class,pass,length(pass)-length(replace(pass,';',''))+1 a from tt
order by a desc
这个只是统计了每一条记录相应字段里姓名的个数,并没有得到我想要的结果最后一段 order 一下不就结了?select class,pass,length(pass)-length(replace(pass,';',''))+1 a from tt
order by a desc
没有错,思路已经有了,难道要把代码完整写出来?
具体如下:(1)、原表:
CREATE TABLE `tab_1` (
`class` int(11) NOT NULL AUTO_INCREMENT,
`pass` varchar(255) NOT NULL,
PRIMARY KEY (`class`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
insert into `tab_1`(`class`,`pass`) values (1,'张三;李四;王五'),(2,'张三'),(3,'张三;李四;王五'),(4,'张三;李四;王五'),(5,'张三;李四;王五'),(6,'王五;赵二'),(7,'赵二;钱大;孙子;周瑜;伍子胥'),(8,'赵二;钱大;孙子;周瑜;伍子胥;王五'),(9,'王五;赵二;孙子;周瑜;伍子胥'),(10,'张三;钱大;孙子;周瑜');(2)、分割后的表:CREATE TABLE `tab_2` (
`class` int(11) NOT NULL,
`passname` varchar(30) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;(3)、存储过程:
/* Procedure structure for procedure `sp_1` *//*!50003 DROP PROCEDURE IF EXISTS `sp_1` */;DELIMITER $$/*!50003 CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_1`()
BEGIN DECLARE classid INT; DECLARE passStr VARCHAR(255); DECLARE passname VARCHAR(30); DECLARE STOP INT DEFAULT 0; DECLARE cur1 CURSOR FOR SELECT class,pass FROM tab_1; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET STOP=1; truncate table tab_2; OPEN cur1; SET classid=NULL,passStr=NULL,passname=NULL; FETCH cur1 INTO classid,passStr; WHILE STOP <> 1 DO IF passStr IS NULL THEN SET passname=NULL; ELSE IF LOCATE(";",passStr)<>0 THEN SET passname=SUBSTRING(passStr,1,LOCATE(";",passStr)-1); SET passStr=SUBSTRING(passStr,LOCATE(";",passStr)+1); ELSE SET passname=passStr; SET passStr=NULL; END IF; END IF; WHILE passname IS NOT NULL DO INSERT INTO tab_2(class,passname)VALUES(classid,passname); IF passStr IS NULL THEN SET passname=NULL; ELSE IF LOCATE(";",passStr)<>0 THEN SET passname=SUBSTRING(passStr,1,LOCATE(";",passStr)-1); SET passStr=SUBSTRING(passStr,LOCATE(";",passStr)+1); ELSE SET passname=passStr; SET passStr=NULL; END IF; END IF; END WHILE; SET classid=NULL,passStr=NULL,passname=NULL; FETCH cur1 INTO classid,passStr; END WHILE; CLOSE cur1; END */$$
DELIMITER ;
(4)、调用存储过程: call sp_1();
(5)、查看汇总:
SELECT passname,COUNT(1) FROM tab_2 GROUP BY passname HAVING COUNT(1)>=5;
应该是这个,看错了:
SELECT passname,COUNT(1) AS num FROM tab_2 GROUP BY passname ORDER BY num DESC LIMIT 5
2、将pass字段按;分割
3、将分割后的数据插入临时表,
结构如下:
1 张三
1 李四
1 王麻子
2 黎明
2 刘德华
2 张学友
4、简单的查询临时表,就可以统计出来了
SELECT A.stname, count(B.classid) AS stcnt
FROM table2 A INNER JOIN table1 B ON LOCATE(CONCAT(';',A.stname,';'), CONCAT(';',B.passed,';'))>0
GROUP BY A.stname
ORDER BY stcnt DESC
LIMIT 5如果没有花名册,可以用存储过程分解出来。