之前在一个项目中遇到过一个统计功能,需要根据各种条件进行统计。然后采用了Java实现,即是将需要的数据直接从数据库中查询出来,然后用Java进行各种加工处理。实现是实现了但是代码却很复杂、可读性极差。于是,想办法直接在数据库中进行加工处理(使用存储过程 ),然后将处理后的数据预先存入表中(新建)。业务上需要统计的时候,就直接调用存储过程,再从存有处理后的数据的表中查询数据。
主要使用了3个存储过程实现
第一个 CREATE DEFINER = `root` @`%` PROCEDURE `statics_proce_year_readorder` ( ) BEGIN DECLARE done BOOLEAN DEFAULT 0; DECLARE var_mcb_id INT; DECLARE var_m_id INT; DECLARE var_mcb_name VARCHAR ( 50 ); DECLARE var_org_name VARCHAR ( 50 ); DECLARE var_expect_id INT; DECLARE var_expect_name VARCHAR ( 30 ); DECLARE var_intestine_num INT; DECLARE var_stomach_num INT; DECLARE var_total_num INT; DECLARE var_years VARCHAR ( 4 ); DECLARE intestine_view_cursor CURSOR FOR SELECT mcb.id AS mcb_id, mcb.NAME AS mcb_name, org.`name` AS org_name, ept.username AS expect_name, ept.id AS expect_id, c.m_id AS m_id, DATE_FORMAT( c.create_time, '%Y' ) AS years, COUNT( c.inspection_subjects ) AS intestine_num FROM `case` c, organization org, medical_conjoined_body mcb, expect ept, checklist cl, endoscopicreport er WHERE c.inspection_subjects = '小肠胶囊' AND c.imcd_id = mcb.id AND org.id = c.inspection_organization_id AND c.expert_id = ept.id AND cl.case_id = c.id AND er.check_no = cl.check_no AND er.audit_status = 2 GROUP BY DATE_FORMAT( c.create_time, '%Y' ), ept.username, mcb.`name`; DECLARE stomach_view_cursor CURSOR FOR SELECT mcb.id AS mcb_id, mcb.NAME AS mcb_name, org.`name` AS org_name, ept.username AS expect_name, ept.id AS expect_id, c.m_id AS m_id, DATE_FORMAT( c.create_time, '%Y' ) AS years, COUNT( c.inspection_subjects ) AS stomach_num FROM `case` c, organization org, medical_conjoined_body mcb, expect ept, checklist cl, endoscopicreport er WHERE c.inspection_subjects = '胃胶囊' AND c.imcd_id = mcb.id AND org.id = c.inspection_organization_id AND c.expert_id = ept.id AND cl.case_id = c.id AND er.check_no = cl.check_no AND er.audit_status = 2 GROUP BY DATE_FORMAT( c.create_time, '%Y' ), ept.username, mcb.`name`; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; OPEN intestine_view_cursor; REPEAT FETCH intestine_view_cursor INTO var_mcb_id, var_mcb_name, var_org_name, var_expect_name, var_expect_id, var_m_id, var_years, var_intestine_num; INSERT IGNORE INTO checklistCountWithYearOfReadorder ( mcb_id, mcb_name, org_name, expect_name, expect_id, m_id, years, intestine_num, stomach_num, total_num ) VALUES ( var_mcb_id, var_mcb_name, var_org_name, var_expect_name, var_expect_id, var_m_id, var_years, var_intestine_num, 0, var_intestine_num ); UNTIL done END REPEAT; CLOSE intestine_view_cursor; SET done = 0; OPEN stomach_view_cursor; REPEAT FETCH stomach_view_cursor INTO var_mcb_id, var_mcb_name, var_org_name, var_expect_name, var_expect_id, var_m_id, var_years, var_stomach_num; INSERT INTO checklistCountWithYearOfReadorder ( mcb_id, mcb_name, org_name, expect_name, expect_id, m_id, years, intestine_num, stomach_num, total_num ) VALUES ( var_mcb_id, var_mcb_name, var_org_name, var_expect_name, var_expect_id, var_m_id, var_years, 0, var_stomach_num, var_stomach_num ) ON DUPLICATE KEY UPDATE stomach_num = var_stomach_num, total_num = intestine_num + var_stomach_num; UNTIL done END REPEAT; CLOSE stomach_view_cursor; SET done = 0; END 第二个 CREATE DEFINER = `root` @`%` PROCEDURE `statics_proce_year_month_readorder` ( IN sysType INT, IN mId INT, IN mcbId INT ) BEGIN DECLARE done BOOLEAN DEFAULT 0; DECLARE var_mcb_id INT; DECLARE var_m_id INT; DECLARE var_mcb_name VARCHAR ( 50 ); DECLARE var_org_name VARCHAR ( 50 ); DECLARE var_expect_id INT; DECLARE var_expect_name VARCHAR ( 30 ); DECLARE var_intestine_num INT; DECLARE var_stomach_num INT; DECLARE var_total_num INT; DECLARE var_years VARCHAR ( 4 ); DECLARE var_months VARCHAR ( 2 ); DECLARE intestine_view_cursor CURSOR FOR SELECT mcb.id AS mcb_id, mcb.`name` AS mcb_name, org.`name` AS org_name, ept.username AS expect_name, ept.id AS expect_id, c.m_id AS m_id, DATE_FORMAT( c.create_time, '%Y' ) AS years, DATE_FORMAT( c.create_time, '%c' ) AS months, COUNT( c.inspection_subjects ) AS intestine_num FROM `case` c, organization org, medical_conjoined_body mcb, expect ept, checklist cl, endoscopicreport er WHERE c.inspection_subjects = '小肠胶囊' AND c.imcd_id = mcb.id AND org.id = c.inspection_organization_id AND c.expert_id = ept.id AND cl.case_id = c.id AND er.check_no = cl.check_no AND er.audit_status = 2 AND ( c.m_id = IF ( IF ( sysType NOT IN ( 0, 2, 3 ), TRUE, FALSE ), mId, c.m_id ) OR c.m_id = IF ( IF ( sysType NOT IN ( 0, 2, 3 ), TRUE, FALSE ), NULL, c.m_id ) ) AND mcb.id = IF ( IF ( sysType NOT IN ( 0, 1, 2 ), TRUE, FALSE ), mcbId, mcb.id ) GROUP BY DATE_FORMAT( c.create_time, '%Y' ), DATE_FORMAT( c.create_time, '%c' ), ept.username; DECLARE stomach_view_cursor CURSOR FOR SELECT mcb.id AS mcb_id, mcb.NAME AS mcb_name, org.`name` AS org_name, ept.username AS expect_name, ept.id AS expect_id, c.m_id AS m_id, DATE_FORMAT( c.create_time, '%Y' ) AS years, DATE_FORMAT( c.create_time, '%c' ) AS months, COUNT( c.inspection_subjects ) AS stomach_num FROM `case` c, organization org, medical_conjoined_body mcb, expect ept, checklist cl, endoscopicreport er WHERE c.inspection_subjects = '胃胶囊' AND c.imcd_id = mcb.id AND org.id = c.inspection_organization_id AND c.expert_id = ept.id AND cl.case_id = c.id AND er.check_no = cl.check_no AND er.audit_status = 2 GROUP BY DATE_FORMAT( c.create_time, '%Y' ), DATE_FORMAT( c.create_time, '%c' ), ept.username;-- DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; DELETE FROM checklistCountOfReadorder; OPEN intestine_view_cursor; IF done = 1 THEN CLOSE intestine_view_cursor; ELSEIF done = 0 THEN REPEAT FETCH intestine_view_cursor INTO var_mcb_id, var_mcb_name, var_org_name, var_expect_name, var_expect_id, var_m_id, var_years, var_months, var_intestine_num; INSERT IGNORE INTO checklistCountOfReadorder ( mcb_id, mcb_name, org_name, expect_name, expect_id, m_id, years, months, intestine_num, stomach_num, total_num ) VALUES ( var_mcb_id, var_mcb_name, var_org_name, var_expect_name, var_expect_id, var_m_id, var_years, var_months, var_intestine_num, 0, var_intestine_num ); UNTIL done END REPEAT; END IF; CLOSE intestine_view_cursor; SET done = 0;-- OPEN stomach_view_cursor; -- -- REPEAT -- FETCH stomach_view_cursor INTO var_mcb_id,var_mcb_name,var_org_name,var_expect_name,var_expect_id,var_m_id,var_years,var_months,var_stomach_num; -- -- INSERT INTO checklistCountOfReadorder(mcb_id,mcb_name,org_name,expect_name,expect_id,m_id,years,months,intestine_num,stomach_num,total_num) VALUES(var_mcb_id,var_mcb_name,var_org_name,var_expect_name,var_expect_id,var_m_id,var_years,var_months,0,var_stomach_num,var_stomach_num) ON DUPLICATE KEY UPDATE stomach_num=var_stomach_num,total_num=intestine_num+var_stomach_num; -- -- UNTIL done END REPEAT; -- -- CLOSE stomach_view_cursor; SET done = 0; END 第三个 CREATE DEFINER = `root` @`%` PROCEDURE `statics_proce_year_month_day_readorder` ( ) BEGIN DECLARE done BOOLEAN DEFAULT 0; DECLARE var_mcb_id INT; DECLARE var_m_id INT; DECLARE var_mcb_name VARCHAR ( 50 ); DECLARE var_org_name VARCHAR ( 50 ); DECLARE var_expect_id INT; DECLARE var_expect_name VARCHAR ( 30 ); DECLARE var_intestine_num INT; DECLARE var_stomach_num INT; DECLARE var_total_num INT; DECLARE var_create_time DATETIME;-- 1、创建游标完成基本数据的统计(胃胶囊v1及小肠胶囊v2) DECLARE intestine_view_cursor CURSOR FOR SELECT mcb.id AS mcb_id, mcb.NAME AS mcb_name, org.`name` AS org_name, ept.username AS expect_name, ept.id AS expect_id, c.m_id AS m_id, DATE_FORMAT( c.create_time, '%Y-%c-%d' ) AS create_time, COUNT( c.inspection_subjects ) AS intestine_num FROM `case` c, organization org, medical_conjoined_body mcb, expect ept, checklist cl, endoscopicreport er WHERE c.inspection_subjects = '小肠胶囊' AND c.imcd_id = mcb.id AND org.id = c.inspection_organization_id AND c.expert_id = ept.id AND cl.case_id = c.id AND er.check_no = cl.check_no AND er.audit_status = 2 GROUP BY DATE_FORMAT( c.create_time, '%Y%c%d' ), ept.username, mcb.`name`; DECLARE stomach_view_cursor CURSOR FOR SELECT mcb.id AS mcb_id, mcb.NAME AS mcb_name, org.`name` AS org_name, ept.username AS expect_name, ept.id AS expect_id, c.m_id AS m_id, DATE_FORMAT( c.create_time, '%Y-%c-%d' ) AS create_time, COUNT( c.inspection_subjects ) AS stomach_num FROM `case` c, organization org, medical_conjoined_body mcb, expect ept, checklist cl, endoscopicreport er WHERE c.inspection_subjects = '胃胶囊' AND c.imcd_id = mcb.id AND org.id = c.inspection_organization_id AND c.expert_id = ept.id AND cl.case_id = c.id AND er.check_no = cl.check_no AND er.audit_status = 2 GROUP BY DATE_FORMAT( c.create_time, '%Y%c%d' ), ept.username, mcb.`name`; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;-- 2、任选一个游标(假定为v1:胃胶囊)中的数据插入到完整表t1信息(页面可直接查询并呈现的信息):则小肠胶囊的数量设置为0,总数量total_num设置为胃胶囊的值 OPEN intestine_view_cursor; REPEAT FETCH intestine_view_cursor INTO var_mcb_id, var_mcb_name, var_org_name, var_expect_name, var_expect_id, var_m_id, var_create_time, var_intestine_num; INSERT IGNORE INTO checklistCountWithYearMonthDayOfReadorder ( mcb_id, mcb_name, org_name, expect_name, expect_id, m_id, create_time, intestine_num, stomach_num, total_num ) VALUES ( var_mcb_id, var_mcb_name, var_org_name, var_expect_name, var_expect_id, var_m_id, var_create_time, var_intestine_num, 0, var_intestine_num ); UNTIL done END REPEAT; CLOSE intestine_view_cursor; SET done = 0;-- 3、取另外一个游标(根据2中的假设则为v2:小肠胶囊)中的数据 插入到完整表t1中: -- 采用insert...on duplicate key update statement: -- a、如果联合唯一键(mcb_id+org_name+expect_id+year+months)重复则更新该条记录,将intestine_num字段的值更新到表t1中 -- 同时,将stomach_num中值和intestine_num的值相加然后传入到total_num字段中去。 -- b、如果联合唯一键不重复则插入数据,同时将stomach_num设置为0,total_num设置为intestine_num的值 OPEN stomach_view_cursor; REPEAT FETCH stomach_view_cursor INTO var_mcb_id, var_mcb_name, var_org_name, var_expect_name, var_expect_id, var_m_id, var_create_time, var_stomach_num; INSERT INTO checklistCountWithYearMonthDayOfReadorder ( mcb_id, mcb_name, org_name, expect_name, expect_id, m_id, create_time, intestine_num, stomach_num, total_num ) VALUES ( var_mcb_id, var_mcb_name, var_org_name, var_expect_name, var_expect_id, var_m_id, var_create_time, 0, var_stomach_num, var_stomach_num ) ON DUPLICATE KEY UPDATE stomach_num = var_stomach_num, total_num = intestine_num + var_stomach_num; UNTIL done END REPEAT; CLOSE stomach_view_cursor; SET done = 0; END虽然用SQL实现的代码量也比较大,但是SQL的逻辑更简单、可读性更高,并且使用Java实现也会写不少的SQL语句,所以,综合来讲使用SQL实现更加容易。