表结构:

5042c99b4f2298e212919c9dc1f82a89.png

表数据:

6893d3fdc3809f3d568bf85b483d4e50.png

期望结果:

d80fd626b63f7215fccd0e2dbb4a46b3.png

虽然这种结果可以通过MySQL中的GROUP_CONCAT函数实现,但是此函数有字节长度限制

SELECT ROW_ID, CAST(CONCAT('[', GROUP_CONCAT('{\'FIELD_ID\'', ' : ', IF(INSTR(VALUE, '[{') = 0, CONCAT('\'', VALUE, '\''), VALUE), '}'), ']') AS BINARY) FROM T_TASK_DATA GROUP BY ROW_ID

DELIMITER $$

USE `mpp_master_data`$$

DROP PROCEDURE IF EXISTS `SP_QUERY_TASK_DATA`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `SP_QUERY_TASK_DATA`()

BEGIN

DECLARE V_FIG INT DEFAULT 0;

DECLARE V_ROW_ID INT;

DECLARE V_FIELD_ID INT;

DECLARE V_FIELD_VALUE VARCHAR(10240);

DECLARE V_CRS_TASK_DATA CURSOR FOR SELECT DISTINCT ROW_ID AS V_ROW_ID FROM T_TASK_DATA LIMIT 0, 200;

DECLARE V_CRS_FIELD_DATA CURSOR FOR SELECT FIELD_ID AS V_FIELD_ID, VALUE AS V_FIELD_VALUE FROM T_TASK_DATA WHERE ROW_ID=V_ROW_ID ORDER BY FIELD_ID ASC;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET V_FIG = 1;

-- 创建临时表

DROP TABLE IF EXISTS TMP_TASK_ROW_DATA;

CREATE TEMPORARY TABLE TMP_TASK_ROW_DATA(ROW_ID INT(10), VALUE VARCHAR(10240), PRIMARY KEY (`ROW_ID`));

-- 打开第一层游标,进行遍历

OPEN V_CRS_TASK_DATA;

ROW_LOOP: LOOP

FETCH V_CRS_TASK_DATA INTO V_ROW_ID;

IF V_FIG = 1 THEN

LEAVE ROW_LOOP;

END IF;

SET @V_VALUE = '';

-- 打开第二层游标,进程遍历

OPEN V_CRS_FIELD_DATA;

FIELD_LOOP: LOOP

FETCH V_CRS_FIELD_DATA INTO V_FIELD_ID, V_FIELD_VALUE;

IF V_FIG = 1 THEN

LEAVE FIELD_LOOP;

END IF;

SET @V_VALUE = CONCAT(@V_VALUE, CONCAT(',{"FIELD_ID": ', V_FIELD_ID, ', "VALUE": "', IFNULL(V_FIELD_VALUE, '') ,'"}'));

END LOOP FIELD_LOOP;

CLOSE V_CRS_FIELD_DATA;

SET V_FIG = 0;

SET @V_VALUE = SUBSTRING(@V_VALUE, 2);

SET @V_VALUE = REPLACE(@V_VALUE, '"', '#');

SET @V_VALUE = REPLACE(@V_VALUE, '\'', '$');

SET @V_SQL = CONCAT('INSERT INTO TMP_TASK_ROW_DATA(ROW_ID, VALUE) VALUES (', V_ROW_ID, ', \'[', @V_VALUE, ']\');');

-- SELECT V_ROW_ID, @V_VALUE, @V_SQL;

PREPARE MAIN_STMT FROM @V_SQL;

EXECUTE MAIN_STMT;

DEALLOCATE PREPARE MAIN_STMT;

END LOOP ROW_LOOP;

CLOSE V_CRS_TASK_DATA;

SELECT * FROM TMP_TASK_ROW_DATA;

DROP TABLE TMP_TASK_ROW_DATA;

END$$

DELIMITER ;

以上第二个游标属于模拟动态,

第二种方式:

MySQL本身是不支持动态游标的,但可以通过(准备语句+视图+静态游标)的方法来近似实现。

参考:

说明:

游标循环 查询和更新是很慢的一件事情

第一层层循环200

第二层循环最大15

执行拼接的SQL插入数据到临时表

总共耗时21秒左右,两层循环耗时16秒左右

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐