有没有办法优化这个存储过程?

时间:2015-07-22 14:02:51

标签: mysql stored-procedures optimization pivot-table

所以我有这个邪恶的长而复杂的存储过程,我根据"旋转"的教程构建了。我想知道在这里精通MySQL的人是否会介意与我讨论,如何使这个更清洁,和/或表现更好。此外,当查询在指定的日期之间没有返回结果时,它会在"调用reading_pivot(...)"中产生MySQL语法错误。子句。

以下是代码:

DELIMITER $$
CREATE DEFINER=`csonet_web_user`@`%` PROCEDURE `reading_pivot`(
    IN begin_date datetime,
    IN end_date datetime,
    IN node_string varchar(255),
    IN sensor_string varchar(255)
)
BEGIN
SET session group_concat_max_len = 4096;
SET @sql = null;
SELECT group_concat(distinct concat('MAX(IF(sensorId = ''', sensorId, ''', collectedValue * multiplier + offset, NULL)) AS ''', sensorId,'''')) INTO @sql FROM
    (
        SELECT inodes.id AS nodeId, from_unixtime(300 * round(unix_timestamp(inodes_data.time)/300)) AS dateCollected, TRIM(inodes.descr) AS parentId,
        1 AS sensorNumber, CONCAT('c', TRIM(cast(inodes.id as char(6) charset latin1)), '_1') AS sensorId, inodes.sensType1 AS sensorTitle, inodes.a1 AS multiplier, inodes.b1 AS offset, inodes_data.sens1 AS collectedValue, 
        inodes_structure_data.sensor1_units AS unitsOfMeasure
            FROM CSO_CITY_15.inodes
            INNER JOIN CSO_CITY_15.inodes_structure_data
                ON inodes.id = inodes_structure_data.id
            INNER JOIN CSO_CITY_15.inodes_data inodes_data
                ON inodes.id = inodes_data.i_id
            WHERE find_in_set(TRIM(cast(inodes.id as char(6) charset latin1)), node_string)
                AND inodes_data.time BETWEEN begin_date AND end_date

        UNION ALL

        SELECT inodes.id, from_unixtime(300 * round(unix_timestamp(inodes_data.time)/300)), TRIM(inodes.descr),
        2, CONCAT('c', TRIM(cast(inodes.id as char(6) charset latin1)), '_2'), inodes.sensType2, inodes.a2, inodes.b2, inodes_data.sens2, inodes_structure_data.sensor2_units
            FROM CSO_CITY_15.inodes
            INNER JOIN CSO_CITY_15.inodes_structure_data
                ON inodes.id = inodes_structure_data.id
            INNER JOIN CSO_CITY_15.inodes_data inodes_data
                ON inodes.id = inodes_data.i_id
            WHERE find_in_set(TRIM(cast(inodes.id as char(6) charset latin1)), node_string)
                AND inodes_data.time BETWEEN begin_date AND end_date

        UNION ALL

        SELECT inodes.id, from_unixtime(300 * round(unix_timestamp(inodes_data.time)/300)), TRIM(inodes.descr),
        3, CONCAT('c', TRIM(cast(inodes.id as char(6) charset latin1)), '_3'), inodes.sensType3, inodes.a3, inodes.b3, inodes_data.sens3, inodes_structure_data.sensor3_units
            FROM CSO_CITY_15.inodes
            INNER JOIN CSO_CITY_15.inodes_structure_data
                ON inodes.id = inodes_structure_data.id
            INNER JOIN CSO_CITY_15.inodes_data inodes_data
                ON inodes.id = inodes_data.i_id
            WHERE find_in_set(TRIM(cast(inodes.id as char(6) charset latin1)), node_string)
                AND inodes_data.time BETWEEN begin_date AND end_date

        UNION ALL

        SELECT inodes.id, from_unixtime(300 * round(unix_timestamp(inodes_data.time)/300)), TRIM(inodes.descr),
        4, CONCAT('c', TRIM(cast(inodes.id as char(6) charset latin1)), '_4'), inodes.sensType4, inodes.a4, inodes.b4, inodes_data.sens4, inodes_structure_data.sensor4_units
            FROM CSO_CITY_15.inodes
            INNER JOIN CSO_CITY_15.inodes_structure_data
                ON inodes.id = inodes_structure_data.id
            INNER JOIN CSO_CITY_15.inodes_data inodes_data
                ON inodes.id = inodes_data.i_id
            WHERE find_in_set(TRIM(cast(inodes.id as char(6) charset latin1)), node_string)
                AND inodes_data.time BETWEEN begin_date AND end_date

    ) sensor_reading
WHERE
    find_in_set(sensorId, sensor_string)
ORDER BY dateCollected;

SET @sql = concat('SELECT dateCollected, ', @sql, ' FROM (
        SELECT inodes.id AS nodeId, from_unixtime(300 * round(unix_timestamp(inodes_data.time)/300)) AS dateCollected, TRIM(inodes.descr) AS parentId,
        1 AS sensorNumber, CONCAT(''c'', TRIM(cast(inodes.id as char(6) charset latin1)), ''_1'') AS sensorId, inodes.sensType1 AS sensorTitle, inodes.a1 AS multiplier, inodes.b1 AS offset, inodes_data.sens1 AS collectedValue, 
        inodes_structure_data.sensor1_units AS unitsOfMeasure
            FROM CSO_CITY_15.inodes
            INNER JOIN CSO_CITY_15.inodes_structure_data
                ON inodes.id = inodes_structure_data.id
            INNER JOIN CSO_CITY_15.inodes_data inodes_data
                ON inodes.id = inodes_data.i_id
            WHERE find_in_set(TRIM(cast(inodes.id as char(6) charset latin1)), ''',node_string,''')
                AND inodes_data.time BETWEEN ''',begin_date,''' AND ''',end_date,'''

        UNION ALL

        SELECT inodes.id, from_unixtime(300 * round(unix_timestamp(inodes_data.time)/300)), TRIM(inodes.descr),
        2, CONCAT(''c'', TRIM(cast(inodes.id as char(6) charset latin1)), ''_2''), inodes.sensType2, inodes.a2, inodes.b2, inodes_data.sens2, inodes_structure_data.sensor2_units
            FROM CSO_CITY_15.inodes
            INNER JOIN CSO_CITY_15.inodes_structure_data
                ON inodes.id = inodes_structure_data.id
            INNER JOIN CSO_CITY_15.inodes_data inodes_data
                ON inodes.id = inodes_data.i_id
            WHERE find_in_set(TRIM(cast(inodes.id as char(6) charset latin1)), ''',node_string,''')
                AND inodes_data.time BETWEEN ''',begin_date,''' AND ''',end_date,'''

        UNION ALL

        SELECT inodes.id, from_unixtime(300 * round(unix_timestamp(inodes_data.time)/300)), TRIM(inodes.descr),
        3, CONCAT(''c'', TRIM(cast(inodes.id as char(6) charset latin1)), ''_3''), inodes.sensType3, inodes.a3, inodes.b3, inodes_data.sens3, inodes_structure_data.sensor3_units
            FROM CSO_CITY_15.inodes
            INNER JOIN CSO_CITY_15.inodes_structure_data
                ON inodes.id = inodes_structure_data.id
            INNER JOIN CSO_CITY_15.inodes_data inodes_data
                ON inodes.id = inodes_data.i_id
            WHERE find_in_set(TRIM(cast(inodes.id as char(6) charset latin1)), ''',node_string,''')
                AND inodes_data.time BETWEEN ''',begin_date,''' AND ''',end_date,'''

        UNION ALL

        SELECT inodes.id, from_unixtime(300 * round(unix_timestamp(inodes_data.time)/300)), TRIM(inodes.descr),
        4, CONCAT(''c'', TRIM(cast(inodes.id as char(6) charset latin1)), ''_4''), inodes.sensType4, inodes.a4, inodes.b4, inodes_data.sens4, inodes_structure_data.sensor4_units
            FROM CSO_CITY_15.inodes
            INNER JOIN CSO_CITY_15.inodes_structure_data
                ON inodes.id = inodes_structure_data.id
            INNER JOIN CSO_CITY_15.inodes_data inodes_data
                ON inodes.id = inodes_data.i_id
            WHERE find_in_set(TRIM(cast(inodes.id as char(6) charset latin1)), ''',node_string,''')
                AND inodes_data.time BETWEEN ''',begin_date,''' AND ''',end_date,'''

    ) sensor_reading WHERE
    find_in_set(sensorId, ''',sensor_string,''')
 group by dateCollected');

PREPARE stmt FROM @sql;
EXECUTE stmt;

END$$
DELIMITER ;

示例结果 call CSO_CITY_3.reading_pivot('2015-07-07','2015-07-08','26121','c26121_1,c26121_2')

+---------------------+--------------------+--------------------+
| dateCollected       | c26121_1           | c26121_2           |
+---------------------+--------------------+--------------------+
| 2015-07-07 00:00:00 | 0.8928999044001102 |   1.73075295612216 |
| 2015-07-07 00:05:00 | 0.8787019047886133 |   1.73075295612216 |
| 2015-07-07 00:10:00 | 0.8928999044001102 |  1.759125955402851 |
| 2015-07-07 00:15:00 | 0.8787019047886133 |   1.73075295612216 |
| 2015-07-07 00:20:00 | 0.8928999044001102 | 1.7023799568414688 |
| 2015-07-07 00:25:00 | 0.8928999044001102 |  1.759125955402851 |
| 2015-07-07 00:30:00 | 0.8928999044001102 |   1.73075295612216 |
| 2015-07-07 00:35:00 | 0.9070979040116072 |  1.759125955402851 |
| 2015-07-07 00:40:00 | 0.8787019047886133 |   1.73075295612216 |
| 2015-07-07 00:45:00 | 0.8928999044001102 |   1.73075295612216 |
| 2015-07-07 00:50:00 |  0.935493903234601 | 1.7023799568414688 |
| 2015-07-07 00:55:00 | 0.8928999044001102 |   1.73075295612216 |
| 2015-07-07 01:00:00 | 0.8928999044001102 |   1.73075295612216 |
| 2015-07-07 01:05:00 | 0.8928999044001102 |   1.73075295612216 |

非常感谢任何和所有的帮助或指导!

1 个答案:

答案 0 :(得分:0)

我建议你动态构造查询,然后执行它。 Here就是一个例子,它是如何运作的。