2.4_3 MySQL 存储过程实战场景


相关链接


前言

  之前在Oracle练习过一次存储过程的使用 记一次Oracle存储过程练习 ,并没有在工作中试用过。这次是第一次在工作实战中使用存储过程,遇到了很多问题,属于面向百度开发。这次数据库类型换成了MySQL5.7,开发存储过程的环境为Navicat 12.1.10。最开始是没有使用存储过程的,使用的Java拼接处理(代码已经删掉,就不放了),200条测试数据执行了约一分钟,效率过低,采用存储大约0.07秒,执行效率是java处理的857倍。
  据某位大佬告诉我,MySQL存储过程的功能不如Oralce强大,但也基本够用了,下面先简单介绍一下存储过程的需求场景(涉及敏感信息已脱敏处理):


一、需求说明

  按照UI原型设计表,上游按照表结构提供数据,分析各类型及数量,展现BI页面效果如下:

这里的苹果,香蕉,西瓜,葡萄的类型是动态表头(这里的苹果、香蕉 可能是其他值,需要从提供的数据中获取),食品类,但生活用品类这两种类别是可以确定的
在这里插入图片描述


二、解决方案


2.1 设计表结构

  由于是动态表头,所以不能够设计成固定的字段来体现数量

在这里插入图片描述

  所以表结构要改造成这样:

在这里插入图片描述
简单介绍一下命名规则

YEAR_1:年,由于YEAR是关键字,加后缀方便使用SELECT YEAR_1,如果字段叫YEAR引用字段需要SELECT “YEAR”;
ORG:organization缩写,表示企业
YEAR_1 和 ORG基本上每个表都有,统一命名方便开发

WD01:维度01
DL01:度量01

  需要上游提供数据的表的建表语句及模拟数据

  • zyqyxczg_a004 商品销量信息主表
-- ----------------------------
-- Table structure for zyqyxczg_a004
-- ----------------------------
DROP TABLE IF EXISTS `zyqyxczg_a004`;
CREATE TABLE `zyqyxczg_a004`  (
  `TB_TIME` date NULL DEFAULT NULL COMMENT '填报时间(YYYY-MM-DD)',
  `TB_ORDER` decimal(20, 0) NULL DEFAULT NULL COMMENT '填报数据指定排序序号',
  `YEAR_1` decimal(20, 0) NULL DEFAULT NULL COMMENT '年',
  `ORG` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '企业简称',
  `WD01` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品分类',
  `WD02` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称',
  `DL01` decimal(20, 0) NULL DEFAULT NULL COMMENT '商品销量'
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '商品销量信息主表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of zyqyxczg_a004
-- ----------------------------
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 1, 2018, '淘宝', '食品', '苹果', 28);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 2, 2018, '淘宝', '食品类', '香蕉', 98);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 3, 2018, '淘宝', '生活用品类', '收纳柜', 12);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 4, 2018, '淘宝', '生活用品类', '地毯', 12);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 5, 2018, '拼多多', '食品', '苹果', 75);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 6, 2018, '拼多多', '食品', '西瓜', 13);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 7, 2018, '拼多多', '生活用品类', '收纳柜', 64);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 8, 2018, '拼多多', '生活用品类', '肥皂盒', 83);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 9, 2018, '京东', '食品', '香蕉', 79);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 10, 2018, '京东', '食品', '葡萄', 54);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 11, 2018, '京东', '生活用品类', '晾衣架', 69);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 12, 2018, '京东', '生活用品类', '地毯', 69);

  zyqyxczg_a004 商品销量信息主表,通过存储过程处理数据后存放到以下四张表:

  • 1.zyqyxczg_a004_b001_type  食品类型子表
  • 2.zyqyxczg_a004_b001_result 食品类各商品销量子表
  • 3.zyqyxczg_a004_b002_type  生活用品类型子表
  • 4.zyqyxczg_a004_b002_result 生活用品类各商品销量子表
-- ----------------------------
-- 1.Table structure for zyqyxczg_a004_b001_type
-- ----------------------------
DROP TABLE IF EXISTS `zyqyxczg_a004_b001_type`;
CREATE TABLE `zyqyxczg_a004_b001_type`  (
  `type_order` int(11) NULL DEFAULT NULL COMMENT '类型排序',
  `type_list` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '食品名称'
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '食品类型子表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- 2.Table structure for zyqyxczg_a004_b001_result
-- ----------------------------
DROP TABLE IF EXISTS `zyqyxczg_a004_b001_result`;
CREATE TABLE `zyqyxczg_a004_b001_result`  (
  `PK_RESULT_ORDER` int(11) NOT NULL AUTO_INCREMENT  COMMENT '主键-结果排序',
  `YEAR_1` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '年',
  `ORG` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '企业简称',
  `DL01` int(11) NULL DEFAULT NULL COMMENT '度量1',
  `DL02` int(11) NULL DEFAULT NULL COMMENT '度量2',
  `DL03` int(11) NULL DEFAULT NULL COMMENT '度量3',
  `DL04` int(11) NULL DEFAULT NULL COMMENT '度量4',
  `DL05` int(11) NULL DEFAULT NULL COMMENT '度量5',
  `DL06` int(11) NULL DEFAULT NULL COMMENT '度量6',
  `DL07` int(11) NULL DEFAULT NULL COMMENT '度量7',
  `DL08` int(11) NULL DEFAULT NULL COMMENT '度量8',
  `DL09` int(11) NULL DEFAULT NULL COMMENT '度量9',
  `DL10` int(11) NULL DEFAULT NULL COMMENT '度量10',
  `result_sum` int(11) NULL DEFAULT NULL COMMENT '总数',
  PRIMARY KEY (`pk_result_order`) USING BTREE
) ENGINE = MyISAM  CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '食品类各商品销量子表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- 3.Table structure for zyqyxczg_a004_b002_type
-- ----------------------------
DROP TABLE IF EXISTS `zyqyxczg_a004_b002_type`;
CREATE TABLE `zyqyxczg_a004_b002_type`  (
  `type_order` int(11) NULL DEFAULT NULL COMMENT '类型排序',
  `type_list` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '食品类型'
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '生活用品类型子表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- 4.Table structure for zyqyxczg_a004_b002_result
-- ----------------------------
DROP TABLE IF EXISTS `zyqyxczg_a004_b002_result`;
CREATE TABLE `zyqyxczg_a004_b002_result`  (
  `PK_RESULT_ORDER` int(11) NOT NULL AUTO_INCREMENT  COMMENT '主键-结果排序',
  `YEAR_1` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '年',
  `ORG` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '企业简称',
  `DL01` int(11) NULL DEFAULT NULL COMMENT '度量1',
  `DL02` int(11) NULL DEFAULT NULL COMMENT '度量2',
  `DL03` int(11) NULL DEFAULT NULL COMMENT '度量3',
  `DL04` int(11) NULL DEFAULT NULL COMMENT '度量4',
  `DL05` int(11) NULL DEFAULT NULL COMMENT '度量5',
  `DL06` int(11) NULL DEFAULT NULL COMMENT '度量6',
  `DL07` int(11) NULL DEFAULT NULL COMMENT '度量7',
  `DL08` int(11) NULL DEFAULT NULL COMMENT '度量8',
  `DL09` int(11) NULL DEFAULT NULL COMMENT '度量9',
  `DL10` int(11) NULL DEFAULT NULL COMMENT '度量10',
  `result_sum` int(11) NULL DEFAULT NULL COMMENT '总数',
  PRIMARY KEY (`pk_result_order`) USING BTREE
) ENGINE = MyISAM  CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '生活用品类各商品销量子表' ROW_FORMAT = Dynamic;

2.2 整体思路介绍

  Step1. 从原表到type表只需要按照以下sql逻辑,按顺序取出

select 
	WD02 as '食品名称'
from 
	cs_groupies_20210317.zyqyxczg_a004
where 
	wd01 ='食品类'
group by 
	WD02 
order by 
-- 保证和UI原型图一致,当出现UI原型图以外的类型时也不会报错
-- 但新类型会按mysql默认排序规则排到某个位置
	FIELD(WD02,'苹果','香蕉','西瓜','葡萄');

------------
苹果
香蕉
西瓜
葡萄

------------
-- 排序里面去掉葡萄测试一下效果
select 
	WD02 as '食品名称'
from 
	cs_groupies_20210317.zyqyxczg_a004
where 
	wd01 ='食品类'
group by 
	WD02 
order by 
	FIELD(WD02,'苹果','香蕉','西瓜');
------------
葡萄
苹果
香蕉
西瓜

  Step2. 使用游标遍历取出的结果集,将序号和类型两个值,拼接到INSERT语句的两个参数,插入type表中

-- SQL模式如下所示(序号、商品名称从游标中遍历获取)
INSERT INTO zyqyxczg_a004_b001_type(type_order,type_list)VALUES(序号,商品名称);
  • Step3. 从原表和type表到result表,同样需要使用存储过程拼接并执行INSERT语句
  • 这里INSERT语句比较复杂,我将其分为三部分【头部、身体、尾部】
    • 头部:INSERT部分,这里year_1,org,result_sum是确定的,但是dlxx的数量是不确定的,是从type表遍历得来的;
    • 身体:SELECT部分,同样dlxx的字段数量是不确定的,需要从type表遍历得来,这里使用了CASE WHEN进行列转行;
    • 尾部:WHERE条件部分,由于year_1和org是联合主键,即同一年同一公司在此表中数据只会有一条,这里year_1和org是从原表遍历来的。
-- 【select和insert部分数据来源】
select type_list from zyqyxczg_a004_b001_type; 
---
苹果
香蕉
西瓜
葡萄

-- 【where部分数据来源】
select distinct 
	t1.year_1,
	t1.org  
from 
	zyqyxczg_a004 T1 
order by
	t1.year_1;
---
2018	京东
2018	拼多多
2018	淘宝


--拼接语句示例
INSERT INTO db_upload_excel.zyqyxczg_a004_b002_result ( year_1, org, dl01, dl02, dl03, dl04,result_sum ) 
SELECT
	year_1,
	org,
	IFNULL( sum( CASE wd02 WHEN '苹果' THEN dl01 END ), 0 ) AS dl01,
	IFNULL( sum( CASE wd02 WHEN '香蕉' THEN dl01 END ), 0 ) AS dl02,
	IFNULL( sum( CASE wd02 WHEN '西瓜' THEN dl01 END ), 0 ) AS dl03,
	IFNULL( sum( CASE wd02 WHEN '葡萄' THEN dl01 END ), 0 ) AS dl04,
	IFNULL( sum( dl01 ), 0 ) AS '总数' 
FROM
	cs_groupies_20210317.zyqyxczg_a004 
WHERE
	wd01 = '食品类' 
	AND year_1 = '2018' 
	AND org = '京东';
  • 整体流程思路示意图:

    在这里插入图片描述
    下面介绍具体开发过程


2.3 存储过程开发

  zyqyxczg_a004_b002*zyqyxczg_a004_b001* 脚本相似,此处就仅展示b001的脚本。


2.3.1 创建存储过程

再次介绍我是用版本是Navicat 12.1.10 不同版本界面可能会有不同

  • Step1.右击函数 选择新建

    在这里插入图片描述

  • Step2.选择过程,完成,存储过程名可以进去再定义

    在这里插入图片描述

  • Step3.直接点击完成,调用存储过程需要输入、输出参数时可以在这里添加,我们这里不需要传参,都是查询后直接执行INSERT语句;

    在这里插入图片描述

  • Step4.新建的存储过程就长这样

    在这里插入图片描述

  • Step5.给出 存储过程名 PROCEDURE ``(创建人DEFINER不熟悉的话不建议修改,就用CURRENT_USER),后点击保存后即可看到新建的存储过程,下面开始编写脚本逻辑

    在这里插入图片描述


2.3.2 zyqyxczg_a004_b001_type

  • Step1.存储过程内容
CREATE DEFINER=CURRENT_USER PROCEDURE `zyqyxczg_a004_b001_type`()
BEGIN
	#Routine body goes here...
	    /* 定义变量 */ 
    	DECLARE order_cursor int unsigned DEFAULT 1; -- 用于拼接insert语句
		DECLARE type_cursor varchar(100) character set 'utf8' DEFAULT null ;-- 商品类型,用于拼接insert语句
		DECLARE done int DEFAULT -1;  -- 用于控制循环是否结束: done=-1继续循环,done=1时退出循环
		
		/* 定义游标 */ 
		DECLARE myCursor CURSOR for 
		select 
			WD02 as '食品名称'
		from 
			cs_groupies_20210317.zyqyxczg_a004
		where 
			wd01 ='食品类'
		group by 
			WD02 
		order by 
			FIELD(WD02,'苹果','香蕉','西瓜','葡萄');
 
	/* 当游标到达尾部时,mysql自动设置done=1 */       
    DECLARE continue handler for not found set done=1;    
		
    /* 打开游标 */    
    OPEN myCursor;    
		
		/* 清空目标表 */ 
		truncate table cs_groupies_20210317.zyqyxczg_a004_b001_type;
		
		/* 循环开始 */    
		myLoop: LOOP
			/* 每次从结果集中获取一条数据,将结果集中的值赋值给变量type_cursor */   
			fetch myCursor into type_cursor;
		  -- 游标到达尾部,退出循环  
			if done = 1 then     
				leave myLoop;    
			end if;    
				
		/* do something */    
    		-- 循环插入问题类型到表中
			INSERT INTO cs_groupies_20210317.zyqyxczg_a004_b001_type(type_order,type_list)
			VALUES(order_cursor,type_cursor);
			
			-- 序号从1开始,每次循环+1
			set order_cursor = order_cursor + 1;
			
   		/* 循环结束 */    
		end loop myLoop;   
		
	/* 关闭游标,释放内存 */ 
	CLOSE myCursor;
	
END
  • Step2.点击保存、运行即可执行存储过程

    在这里插入图片描述

  • Step3.在看一下type表内已经有数据了(可以手动Truncate表再执行看看,确认一下)

    在这里插入图片描述

2.3.3 zyqyxczg_a004_b001_result

  • Step1.存储过程内容
CREATE DEFINER=CURRENT_USER PROCEDURE `zyqyxczg_a004_b001_result`()
BEGIN
	# Routine body goes here...
    /* myCursorInsertSelect定义变量 */ 
		/* insert部分 */
		-- 【来自查询结果】用于拼接INSERT语句部分 DLXX的数字
		DECLARE insert_id_cursor_1 int unsigned DEFAULT 1; 
		-- 【来自拼接字符串0】上一个变量小于10时前面拼0
		DECLARE insert_id_cursor_2 varchar(200) character set 'utf8' DEFAULT null ; 
		-- 【来自拼接sql】拼接insert第二部分sql
		DECLARE insert_sql varchar(5000) character set 'utf8' DEFAULT 'insert into cs_groupies_20210317.zyqyxczg_a004_b001_result ( year_1,org' ;

		/* select部分 */
		-- 【来自查询结果】用于拼接select部分的食品名称
		DECLARE select_type_cursor varchar(4000) character set 'utf8' DEFAULT null ;
		-- 【来自拼接sql】拼接insert第一部分sql
		DECLARE select_sql varchar(5000) character set 'utf8' DEFAULT 'select \r\n  year_1,\r\n  org';
		
		
    /* myCursorWhere定义变量 */
	/* where部分 */
		-- 【来自查询结果】 用于拼接wherer部分的公司名称
	  DECLARE where_org_cursor varchar(4000) character set 'utf8' DEFAULT null ;
		-- 【来自查询结果】 用于拼接wherer部分的年
	  DECLARE where_year_cursor varchar(4000) character set 'utf8' DEFAULT null ;
		-- 【来自拼接sql】拼接where第二部分sql
		DECLARE where_sql varchar(5000) character set 'utf8' DEFAULT " \r\nwhere \r\n  wd01='食品类' \r\n  and year_1='";
		
		/* 执行sql语句 定义变量 */ 
		DECLARE all_sql_execute varchar(5000) character set 'utf8' DEFAULT null ;
		/* 控制循环 定义变量  -1:继续 ; 0:退出循环  */ 
		DECLARE done int DEFAULT -1; 
		
		/* 定义游标 */
		/* 游标1:select和insert部分 */
		DECLARE myCursorInsertSelect CURSOR for select type_list from zyqyxczg_a004_b001_type; 
		/* 游标2:where部分 */
		DECLARE myCursorWhere CURSOR for 
			select distinct 
				t1.year_1,
				t1.org  
			from 
				zyqyxczg_a004 T1 
			order by
				t1.year_1;
	
	/* 当游标到达尾部时,mysql自动设置done=1 */       
    DECLARE continue handler for not found set done=1;
		
    /* Insert和Select部分 打开游标 */    
    OPEN myCursorInsertSelect;    
		
		-- 先调用type存储过程,获取最新的食品名称列表;
		CALL zyqyxczg_a004_b001_type;
		-- 清空表
		truncate table cs_groupies_20210317.zyqyxczg_a004_b001_result;
		
		/* 循环开始 */    
		myLoop: LOOP    
			fetch myCursorInsertSelect into select_type_cursor;
		  /* 游标到达尾部,退出循环 */  
			if done = 1 then  
				/* 推出循环前在拼接上最后一个字段 ,result_sum */
				set insert_sql = concat(insert_sql,",result_sum ) ");
				set select_sql = concat(select_sql,",\r\n  IFNULL(sum(dl01),0) as '总数'	\r\nfrom \r\n  cs_groupies_20210317.zyqyxczg_a004");	
				-- 测试拼接结果
				 # select all_sql_execute; 
				leave myLoop;    
			end if;    
				
		/* do something */    
			/* 
			 * 如果insert_id_cursor_1<10 
			 * 例如insert_id_cursor_1=5,如则在前面拼接0, 即05 ;如果≥10,则直接取值
			 */
			if insert_id_cursor_1 < 10 THEN
				set insert_id_cursor_2 = concat('0',insert_id_cursor_1);
			else 
				set insert_id_cursor_2 = insert_id_cursor_1;
			end if;
			/* 循环拼接select_sql和insert_sql */
			-- 拼接sql查询部分
			set select_sql = concat(select_sql,",\r\n  IFNULL(sum(case wd02 when '",select_type_cursor,"' then dl01 end),0) as dl",insert_id_cursor_2);
			
			-- 拼接sqlinsert部分
			set insert_sql=concat(insert_sql,",dl",insert_id_cursor_2);
			
		-- 每次循环序号+1
			-- select all_sql_execute;
			set insert_id_cursor_1=insert_id_cursor_1+1;
    /* 循环结束 */    
		end loop myLoop;   
		
		CLOSE myCursorInsertSelect;
		
		
		/* Where条件部分 打开游标 */    
		OPEN myCursorWhere; 
			/* 此时done=1 重新赋值为-1 否则会直接跳出循环*/
			set done=-1;
			/* 循环拼接where条件中的year和org*/
			myLoop: LOOP    
				fetch myCursorWhere into where_year_cursor,where_org_cursor;
				-- 游标到达尾部,退出循环  
				if done = 1 then  
					-- 测试拼接结果
					select @sql; 
					leave myLoop;    
				end if;    
				
				/* do something */    
				-- 循环插入查询结果到表zyqyxczg_a004_b001_result中
				SET @sql=concat(insert_sql,
					"\r\n",
					select_sql,
					where_sql,
					where_year_cursor,
					"' and org='",
					where_org_cursor,
					"';");
				PREPARE all_sql_execute FROM @sql;
				EXECUTE all_sql_execute;
			/* 循环结束 */    
			end loop myLoop;   
		
		CLOSE myCursorWhere;	
			
END
  • Step2.点击保存、运行即可执行存储过程

    在这里插入图片描述

  • Step3. 点击结果1,可以看到在存储过程里打印到控制台的最后一条查询语句(用于调试拼接结果)

    在这里插入图片描述

  • Step4.将结果复制出来,并执行Select部分语句,这个查询结果就是存储过程执行的最后一条INSERT数据

    在这里插入图片描述

  • Step5.在看一下type表内已经有数据了(可以手动Truncate表再执行看看,确认一下)

    在这里插入图片描述


2.3.4 一键执行多个存储过程

  • 存储过程内容
CREATE DEFINER=CURRENT_USER PROCEDURE `dynamic_refresh`()
BEGIN
	#Routine body goes here...
		-- 刷新所有动态表头的数据(result里面已经调用了type)
		CALL db_upload_excel.zyqyxczg_a004_b001_result;
		CALL db_upload_excel.zyqyxczg_a004_b002_result;
		
END

2.3.5 定时执行存储过程

定时从2021-03-17 开始每天0点执行一次,获取新的结果

  • Step1.右击事件,选择新建事件

    在这里插入图片描述

  • Step2.在定义中输入执行的sql语句

    在这里插入图片描述

    CALL cs_groupies_20210317.dynamic_refresh
    
  • Step3.在计划中选择开始时间和执行频率

    在这里插入图片描述

  • Step4.注释可以不填,点击保存,输入定时任务名称

    在这里插入图片描述

  • Step5.在事件里可以看到刚才创建的任务

    在这里插入图片描述


3 Java代码

    public JsonData select04(Map<String, String[]> params) {
        params.forEach((key, values) -> logger.debug("参数:{},值{}", key, values));
        JsonData result = new JsonData();
        String tableNameSql = "SELECT type_list AS \"tableName\" FROM zyqyxczg_a004_b001_type";
        List<Map<String, String>> tableNameDatas = dbUtils.excuteSelect(tableNameSql, index);
        List<String> tableNameList = tableNameDatas.stream().map(data -> data.get("tableName")).collect(Collectors.toList());
        result.setExtendData(commontService.appendSql(params, tableNameList, "zyqyxczg_a004_b001_result"));
        tableNameList.add(0, "序号");
        tableNameList.add(1, "企业名称");
        tableNameList.add("总数");
        result.setOtherList(commontService.assemblyTableNameData(tableNameList));
        return result;
    }

4 表结构及数据导出

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for zyqyxczg_a004
-- ----------------------------
DROP TABLE IF EXISTS `zyqyxczg_a004`;
CREATE TABLE `zyqyxczg_a004`  (
  `TB_TIME` date NULL DEFAULT NULL COMMENT '填报时间(YYYY-MM-DD)',
  `TB_ORDER` decimal(20, 0) NULL DEFAULT NULL COMMENT '填报数据指定排序序号',
  `YEAR_1` decimal(20, 0) NULL DEFAULT NULL COMMENT '年',
  `ORG` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '企业简称',
  `WD01` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品分类',
  `WD02` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称',
  `DL01` decimal(20, 0) NULL DEFAULT NULL COMMENT '商品销量'
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '商品销量信息表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of zyqyxczg_a004
-- ----------------------------
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 1, 2018, '淘宝', '食品类', '苹果', 28);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 2, 2018, '淘宝', '食品类', '香蕉', 98);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 3, 2018, '淘宝', '生活用品类', '收纳柜', 12);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 4, 2018, '淘宝', '生活用品类', '地毯', 12);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 5, 2018, '拼多多', '食品类', '苹果', 75);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 6, 2018, '拼多多', '食品类', '西瓜', 13);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 7, 2018, '拼多多', '生活用品类', '收纳柜', 64);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 8, 2018, '拼多多', '生活用品类', '肥皂盒', 83);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 9, 2018, '京东', '食品类', '香蕉', 79);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 10, 2018, '京东', '食品类', '葡萄', 54);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 11, 2018, '京东', '生活用品类', '晾衣架', 69);
INSERT INTO `zyqyxczg_a004` VALUES ('2020-03-04', 12, 2018, '京东', '生活用品类', '地毯', 69);

-- ----------------------------
-- Table structure for zyqyxczg_a004_b001_result
-- ----------------------------
DROP TABLE IF EXISTS `zyqyxczg_a004_b001_result`;
CREATE TABLE `zyqyxczg_a004_b001_result`  (
  `PK_RESULT_ORDER` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键-结果排序',
  `YEAR_1` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '年',
  `ORG` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '企业简称',
  `DL01` int(11) NULL DEFAULT NULL COMMENT '度量1',
  `DL02` int(11) NULL DEFAULT NULL COMMENT '度量2',
  `DL03` int(11) NULL DEFAULT NULL COMMENT '度量3',
  `DL04` int(11) NULL DEFAULT NULL COMMENT '度量4',
  `DL05` int(11) NULL DEFAULT NULL COMMENT '度量5',
  `DL06` int(11) NULL DEFAULT NULL COMMENT '度量6',
  `DL07` int(11) NULL DEFAULT NULL COMMENT '度量7',
  `DL08` int(11) NULL DEFAULT NULL COMMENT '度量8',
  `DL09` int(11) NULL DEFAULT NULL COMMENT '度量9',
  `DL10` int(11) NULL DEFAULT NULL COMMENT '度量10',
  `result_sum` int(11) NULL DEFAULT NULL COMMENT '总数',
  PRIMARY KEY (`PK_RESULT_ORDER`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '食品类各商品销量子表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of zyqyxczg_a004_b001_result
-- ----------------------------
INSERT INTO `zyqyxczg_a004_b001_result` VALUES (1, '2018', '京东', 0, 79, 0, 54, NULL, NULL, NULL, NULL, NULL, NULL, 133);
INSERT INTO `zyqyxczg_a004_b001_result` VALUES (2, '2018', '拼多多', 75, 0, 13, 0, NULL, NULL, NULL, NULL, NULL, NULL, 88);
INSERT INTO `zyqyxczg_a004_b001_result` VALUES (3, '2018', '淘宝', 28, 98, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, 126);

-- ----------------------------
-- Table structure for zyqyxczg_a004_b001_type
-- ----------------------------
DROP TABLE IF EXISTS `zyqyxczg_a004_b001_type`;
CREATE TABLE `zyqyxczg_a004_b001_type`  (
  `type_order` int(11) NULL DEFAULT NULL COMMENT '类型排序',
  `type_list` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '食品名称'
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '食品类型子表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of zyqyxczg_a004_b001_type
-- ----------------------------
INSERT INTO `zyqyxczg_a004_b001_type` VALUES (1, '苹果');
INSERT INTO `zyqyxczg_a004_b001_type` VALUES (2, '香蕉');
INSERT INTO `zyqyxczg_a004_b001_type` VALUES (3, '西瓜');
INSERT INTO `zyqyxczg_a004_b001_type` VALUES (4, '葡萄');

-- ----------------------------
-- Table structure for zyqyxczg_a004_b002_result
-- ----------------------------
DROP TABLE IF EXISTS `zyqyxczg_a004_b002_result`;
CREATE TABLE `zyqyxczg_a004_b002_result`  (
  `PK_RESULT_ORDER` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键-结果排序',
  `YEAR_1` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '年',
  `ORG` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '企业简称',
  `DL01` int(11) NULL DEFAULT NULL COMMENT '度量1',
  `DL02` int(11) NULL DEFAULT NULL COMMENT '度量2',
  `DL03` int(11) NULL DEFAULT NULL COMMENT '度量3',
  `DL04` int(11) NULL DEFAULT NULL COMMENT '度量4',
  `DL05` int(11) NULL DEFAULT NULL COMMENT '度量5',
  `DL06` int(11) NULL DEFAULT NULL COMMENT '度量6',
  `DL07` int(11) NULL DEFAULT NULL COMMENT '度量7',
  `DL08` int(11) NULL DEFAULT NULL COMMENT '度量8',
  `DL09` int(11) NULL DEFAULT NULL COMMENT '度量9',
  `DL10` int(11) NULL DEFAULT NULL COMMENT '度量10',
  `result_sum` int(11) NULL DEFAULT NULL COMMENT '总数',
  PRIMARY KEY (`PK_RESULT_ORDER`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '生活用品类各商品销量子表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Table structure for zyqyxczg_a004_b002_type
-- ----------------------------
DROP TABLE IF EXISTS `zyqyxczg_a004_b002_type`;
CREATE TABLE `zyqyxczg_a004_b002_type`  (
  `type_order` int(11) NULL DEFAULT NULL COMMENT '类型排序',
  `type_list` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '食品类型'
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '生活用品类型子表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Procedure structure for dynamic_refresh
-- ----------------------------
DROP PROCEDURE IF EXISTS `dynamic_refresh`;
delimiter ;;
CREATE PROCEDURE `dynamic_refresh`()
BEGIN
	#Routine body goes here...
		-- 刷新所有动态表头的数据(result里面已经调用了type)
		CALL db_upload_excel.zyqyxczg_a004_b001_result;
		CALL db_upload_excel.zyqyxczg_a004_b002_result;
		
END
;;
delimiter ;

-- ----------------------------
-- Procedure structure for zyqyxczg_a004_b001_result
-- ----------------------------
DROP PROCEDURE IF EXISTS `zyqyxczg_a004_b001_result`;
delimiter ;;
CREATE PROCEDURE `zyqyxczg_a004_b001_result`()
BEGIN
	# Routine body goes here...
    /* myCursorInsertSelect定义变量 */ 
		/* insert部分 */
			-- 【来自查询结果】用于拼接INSERT语句部分 DLXX的数字
		DECLARE insert_id_cursor_1 int unsigned DEFAULT 1; 
			-- 【来自拼接字符串0】上一个变量小于10时前面拼0
		DECLARE insert_id_cursor_2 varchar(200) character set 'utf8' DEFAULT null ; 
			-- 【来自拼接sql】拼接insert第二部分sql
		DECLARE insert_sql varchar(5000) character set 'utf8' DEFAULT 'insert into cs_groupies_20210317.zyqyxczg_a004_b001_result ( year_1,org' ;

		/* select部分 */
			-- 【来自查询结果】用于拼接select部分的食品名称
		DECLARE select_type_cursor varchar(4000) character set 'utf8' DEFAULT null ;
			-- 【来自拼接sql】拼接insert第一部分sql
		DECLARE select_sql varchar(5000) character set 'utf8' DEFAULT 'select \r\n  year_1,\r\n  org';
		
		
    /* myCursorWhere定义变量 */
		/* where部分 */
			-- 【来自查询结果】 用于拼接wherer部分的公司名称
	  DECLARE where_org_cursor varchar(4000) character set 'utf8' DEFAULT null ;
			-- 【来自查询结果】 用于拼接wherer部分的年
	  DECLARE where_year_cursor varchar(4000) character set 'utf8' DEFAULT null ;
			-- 【来自拼接sql】拼接where第二部分sql
		DECLARE where_sql varchar(5000) character set 'utf8' DEFAULT " \r\nwhere \r\n  wd01='食品类' \r\n  and year_1='";
		
		/* 执行sql语句 定义变量 */ 
		DECLARE all_sql_execute varchar(5000) character set 'utf8' DEFAULT null ;
		/* 控制循环 定义变量  -1:继续 ; 0:退出循环  */ 
		DECLARE done int DEFAULT -1; 
		
		/* 定义游标 */
		/* 游标1:select和insert部分 */
		DECLARE myCursorInsertSelect CURSOR for select type_list from zyqyxczg_a004_b001_type; 
		/* 游标2:where部分 */
		DECLARE myCursorWhere CURSOR for 
			select distinct 
				t1.year_1,
				t1.org  
			from 
				zyqyxczg_a004 T1 
			order by
				t1.year_1;
	
		/* 当游标到达尾部时,mysql自动设置done=1 */       
    DECLARE continue handler for not found set done=1;
		
    /* Insert和Select部分 打开游标 */    
    OPEN myCursorInsertSelect;    
		
		-- 动态获取最新问题类型
		CALL zyqyxczg_a004_b001_type;
		-- 清空表
		truncate table cs_groupies_20210317.zyqyxczg_a004_b001_result;
		
		/* 循环开始 */    
		myLoop: LOOP    
			fetch myCursorInsertSelect into select_type_cursor;
		  /* 游标到达尾部,退出循环 */  
			if done = 1 then  
				/* 推出循环前在拼接上最后一个字段 ,result_sum */
				set insert_sql = concat(insert_sql,",result_sum ) ");
				set select_sql = concat(select_sql,",\r\n  IFNULL(sum(dl01),0) as '总数'	\r\nfrom \r\n  cs_groupies_20210317.zyqyxczg_a004");	
				-- 测试拼接结果
				 # select all_sql_execute; 
				leave myLoop;    
			end if;    
				
		/* do something */    
			/* 
			 * 如果insert_id_cursor_1<10 
			 * 例如insert_id_cursor_1=5,如则在前面拼接0, 即05 ;如果≥10,则直接取值
			 */
			if insert_id_cursor_1 < 10 THEN
				set insert_id_cursor_2 = concat('0',insert_id_cursor_1);
			else 
				set insert_id_cursor_2 = insert_id_cursor_1;
			end if;
			/* 循环拼接select_sql和insert_sql */
			-- 拼接sql查询部分
			set select_sql = concat(select_sql,",\r\n  IFNULL(sum(case wd02 when '",select_type_cursor,"' then dl01 end),0) as dl",insert_id_cursor_2);
			
			-- 拼接sqlinsert部分
			set insert_sql=concat(insert_sql,",dl",insert_id_cursor_2);
			
		-- 每次循环序号+1
			-- select all_sql_execute;
			set insert_id_cursor_1=insert_id_cursor_1+1;
    /* 循环结束 */    
		end loop myLoop;   
		
		CLOSE myCursorInsertSelect;
		
		
		/* Where条件部分 打开游标 */    
		OPEN myCursorWhere; 
			/* 此时done=1 重新赋值为-1 否则会直接跳出循环*/
			set done=-1;
			/* 循环拼接where条件中的year和org*/
			myLoop: LOOP    
				fetch myCursorWhere into where_year_cursor,where_org_cursor;
				-- 游标到达尾部,退出循环  
				if done = 1 then  
					-- 测试拼接结果
					select @sql; 
					leave myLoop;    
				end if;    
				
				/* do something */    
				-- 循环插入查询结果到表zyqyxczg_a004_b001_result中
				SET @sql=concat(insert_sql,"\r\n",select_sql,where_sql,where_year_cursor,"' and org='",where_org_cursor,"';");
				PREPARE all_sql_execute FROM @sql;
				EXECUTE all_sql_execute;
			/* 循环结束 */    
			end loop myLoop;   
		
		CLOSE myCursorWhere;	
			
END
;;
delimiter ;

-- ----------------------------
-- Procedure structure for zyqyxczg_a004_b001_type
-- ----------------------------
DROP PROCEDURE IF EXISTS `zyqyxczg_a004_b001_type`;
delimiter ;;
CREATE PROCEDURE `zyqyxczg_a004_b001_type`()
BEGIN
	#Routine body goes here...
	    /* 定义变量 */ 
    	DECLARE order_cursor int unsigned DEFAULT 1; -- 用于拼接insert语句
		DECLARE type_cursor varchar(100) character set 'utf8' DEFAULT null ;-- 商品类型,用于拼接insert语句
		DECLARE done int DEFAULT -1;  -- 用于控制循环是否结束: done=-1继续循环,done=1时退出循环
		
		/* 定义游标 */ 
		DECLARE myCursor CURSOR for 
		select 
			WD02 as '食品名称'
		from 
			cs_groupies_20210317.zyqyxczg_a004
		where 
			wd01 ='食品类'
		group by 
			WD02 
		order by 
			FIELD(WD02,'苹果','香蕉','西瓜','葡萄');
 
	/* 当游标到达尾部时,mysql自动设置done=1 */       
    DECLARE continue handler for not found set done=1;    
		
    /* 打开游标 */    
    OPEN myCursor;    
		
		/* 清空目标表 */ 
		truncate table cs_groupies_20210317.zyqyxczg_a004_b001_type;
		
		/* 循环开始 */    
		myLoop: LOOP
			/* 每次从结果集中获取一条数据,将结果集中的值赋值给变量type_cursor */   
			fetch myCursor into type_cursor;
		  -- 游标到达尾部,退出循环  
			if done = 1 then     
				leave myLoop;    
			end if;    
				
		/* do something */    
    		-- 循环插入问题类型到表中
			INSERT INTO cs_groupies_20210317.zyqyxczg_a004_b001_type(type_order,type_list)
			VALUES(order_cursor,type_cursor);
			
			-- 序号从1开始,每次循环+1
			set order_cursor = order_cursor + 1;
			
   		/* 循环结束 */    
		end loop myLoop;   
		
	/* 关闭游标,释放内存 */ 
	CLOSE myCursor;
	
END
;;
delimiter ;

-- ----------------------------
-- Event structure for 每天0点刷新动态表头
-- ----------------------------
DROP EVENT IF EXISTS `每天0点刷新动态表头`;
delimiter ;;
CREATE EVENT `每天0点刷新动态表头`
ON SCHEDULE
EVERY '1' DAY STARTS '2021-03-17 00:00:00'
DO CALL cs_groupies_20210317.dynamic_refresh
;;
delimiter ;

SET FOREIGN_KEY_CHECKS = 1;


21-03-17

M

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值