mysql 存储过程实现根据开始结束时间动态补点,关联查询

1.场景声明:在用报表工具开发报表时,由于数据查询结果依赖数据库中现有的数据,当筛选条件在数据库中无命中记录时查询结果往往是空的,这本符合条件,但有时用户又希望看到筛选条件全覆盖的查询结果,为此,sql语句必须根据查询结果动态伸缩,以达到预期的效果

2.实现思路:由于这种复杂的数据结果往往无法将查询的sql语句写死,需要动态构建sql语句,所以考虑用存储过程实现,存储过程只传入参的筛选条件,存储过程根据一定的规则while循环将需要的点补全后作为表A,将条件查询结果集作为表B,通过B right join A实现补点效果

3.表B查询sql及查询结果:

SELECT REPLACE
    ( h.日期, ":00", "h" ) AS 日期,
    round( REPLACE ( format( h.上限值, 2 ), ',', '' ), 2 ) AS 上限值 
FROM
    (
SELECT
    concat( substr( g.日期, 6, 6 ), "(", g.时刻, ")" ) AS 日期,
    ( g.统调负荷 + g.东送负荷 - ( g.火电检修容量 - g.自备检修容量 ) * 0.5 * 0.9 - g.自备检修容量 * 0.85 * 0.9 ) AS 上限值 
FROM
    (
SELECT
    e.日期,
    e.时刻,
    e.统调负荷,
    e.东送负荷,
    f.自备检修容量,
    f.火电检修容量 
FROM
    (
SELECT
    a.日期,
    a.时刻,
    a.预测值 AS 统调负荷,
    b.预测值 AS 东送负荷 
FROM
    (
SELECT
    ( @ROW := @ROW + 1 ) AS 序号,
    businessTime AS 时刻,
    businessDate AS 日期,
    planValue AS 预测值 
FROM
    ( SELECT @ROW := 0 ) t,
    next_nified_dispatch_load_forecast 
WHERE
    businessDate >= '2022-06-07' 
    AND businessDate <= '2022-06-17' 
GROUP BY
    businessDate,
    businessTime 
ORDER BY
    ( @ROW := @ROW + 1 ) 
    ) a
    INNER JOIN (
SELECT
    ( @ROW := @ROW + 1 ) AS 序号,
    businessTime AS 时刻,
    businessDate AS 日期,
    planValue AS 预测值 
FROM
    ( SELECT @ROW := 0 ) t,
    next_eastward_ran_plan 
WHERE
    businessDate >= '2022-06-07' 
    AND businessDate <= '2022-06-17' 
GROUP BY
    businessDate,
    businessTime 
ORDER BY
    ( @ROW := @ROW + 1 ) 
    ) b ON a.日期 = b.日期 
    AND a.时刻 = b.时刻 
ORDER BY
    a.日期,
    a.时刻 
    ) e
    LEFT JOIN (
SELECT
    c.日期,
    c.自备检修容量,
    d.火电检修容量 
FROM
    (
SELECT
    ( @ROW := @ROW + 1 ) AS 序号,
    ( SELECT SUM( captive_capacity ) 自备总容量 FROM spot_base_data.t_node_capacity_common WHERE type = 1 ) - CAST( ROUND( SUM( capacity ), 3 ) AS DECIMAL ) 自备检修容量,
    businessDate AS 日期 
FROM
    ( SELECT @ROW := 0 ) t,
    maintenance_information_import 
WHERE
    businessDate >= '2022-06-07' 
    AND businessDate <= '2022-06-17' 
    AND equipment = '机组' 
    AND equipmentDispatchingName REGEXP 'xx|yy' 
GROUP BY
    businessDate 
ORDER BY
    ( @ROW := @ROW + 1 ) 
    ) c
    INNER JOIN (
SELECT
    ( @ROW := @ROW + 1 ) AS 序号,
    ( SELECT SUM( power_installation_capacity ) + SUM( captive_capacity ) 装机总容量 FROM spot_base_data.t_node_capacity_common WHERE type = 1 ) - CAST( ROUND( SUM( capacity ), 3 ) AS DECIMAL ) 火电检修容量,
    businessDate AS 日期 
FROM
    ( SELECT @ROW := 0 ) t,
    maintenance_information_import 
WHERE
    businessDate >= '2022-06-07' 
    AND businessDate <= '2022-06-17' 
    AND equipment = '机组' 
GROUP BY
    businessDate 
ORDER BY
    ( @ROW := @ROW + 1 ) 
    ) d ON c.日期 = d.日期 
    ) f ON f.日期 = e.日期 
    ) g 
    ) h 
WHERE
    日期 REGEXP '04:00|06:00|08:00|10:00|12:00|14:00|16:00|18:00|20:00|22:00|11:00|17:00|05:00'

查询结果:

日期    上限值

06-07(04h) 12776.67
06-07(05h) 12782.67
06-07(06h) 13387.67
06-07(08h) 14223.27
06-07(10h) 15172.57
06-07(11h) 15562.17
06-07(12h) 14907.97
06-07(14h) 14273.77
06-07(16h) 14591.17
06-07(17h) 15226.17
06-07(18h) 15200.47
06-07(20h) 15762.37
06-07(22h) 15800.77
06-08(04h)
06-08(05h)
06-08(06h)
06-08(08h)
06-08(10h)
06-08(11h)
06-08(12h)
06-08(14h)
06-08(16h)
06-08(17h)
06-08(18h)
06-08(20h)
06-08(22h)
06-09(04h) 13330.37
06-09(05h) 13403.77
06-09(06h) 13882.47
06-09(08h) 14784.47
06-09(10h) 15672.77
06-09(11h) 16096.77
06-09(12h) 15407.07
06-09(14h) 14846.77
06-09(16h) 15237.47
06-09(17h) 15840.17
06-09(18h) 15751.07
06-09(20h) 16016.47
06-09(22h) 15933.47
06-10(04h)
06-10(05h)
06-10(06h)
06-10(08h)
06-10(10h)
06-10(11h)
06-10(12h)
06-10(14h)
06-10(16h)
06-10(17h)
06-10(18h)
06-10(20h)
06-10(22h)
06-11(04h)
06-11(05h)
06-11(06h)
06-11(08h)
06-11(10h)
06-11(11h)
06-11(12h)
06-11(14h)
06-11(16h)
06-11(17h)
06-11(18h)
06-11(20h)
06-11(22h)

结果可见查询缺少06-12日到06-17日的数据

4.A需借助存储过程动态构建

drop procedure getrange;
CREATE PROCEDURE getrange ( IN began date, IN eds date)
BEGIN
    declare sqlx text;
    set @sqlx = '';
    WHILE began <= eds 
        DO
        SET @sqlx = concat( @sqlx,'select  "', RIGHT ( began, 5 ), '(04h)', '"  as date union ' );
        SET @sqlx = concat( @sqlx,'select  "', RIGHT ( began, 5 ), '(05h)', '"  as date union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(06h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(08h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(10h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(11h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(12h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(14h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(16h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(17h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(18h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(20h)', '" as date  union ' );
        if began = eds then
            SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(22h)" as date');
        else
            SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(22h)', '" as date union ' );
        end if;
        SET began = adddate( began, 1 );
    END WHILE;
    PREPARE stmt FROM @sqlx;
    EXECUTE stmt;
END;

调用和结果:

CALL getrange ('2022-06-07','2022-06-17' );

date

06-07(04h)
06-07(05h)
06-07(06h)
06-07(08h)
06-07(10h)
06-07(11h)
06-07(12h)
06-07(14h)
06-07(16h)
06-07(17h)
06-07(18h)
06-07(20h)
06-07(22h)
06-08(04h)
06-08(05h)
06-08(06h)
06-08(08h)
06-08(10h)
06-08(11h)
06-08(12h)
06-08(14h)
06-08(16h)
06-08(17h)
06-08(18h)
06-08(20h)
06-08(22h)
06-09(04h)
06-09(05h)
06-09(06h)
06-09(08h)
06-09(10h)
06-09(11h)
06-09(12h)
06-09(14h)
06-09(16h)
06-09(17h)
06-09(18h)
06-09(20h)
06-09(22h)
06-10(04h)
06-10(05h)
06-10(06h)
06-10(08h)
06-10(10h)
06-10(11h)
06-10(12h)
06-10(14h)
06-10(16h)
06-10(17h)
06-10(18h)
06-10(20h)
06-10(22h)
06-11(04h)
06-11(05h)
06-11(06h)
06-11(08h)
06-11(10h)
06-11(11h)
06-11(12h)
06-11(14h)
06-11(16h)
06-11(17h)
06-11(18h)
06-11(20h)
06-11(22h)
06-12(04h)
06-12(05h)
06-12(06h)
06-12(08h)
06-12(10h)
06-12(11h)
06-12(12h)
06-12(14h)
06-12(16h)
06-12(17h)
06-12(18h)
06-12(20h)
06-12(22h)
06-13(04h)
06-13(05h)
06-13(06h)
06-13(08h)
06-13(10h)
06-13(11h)
06-13(12h)
06-13(14h)
06-13(16h)
06-13(17h)
06-13(18h)
06-13(20h)
06-13(22h)
06-14(04h)
06-14(05h)
06-14(06h)
06-14(08h)
06-14(10h)
06-14(11h)
06-14(12h)
06-14(14h)
06-14(16h)
06-14(17h)
06-14(18h)
06-14(20h)
06-14(22h)
06-15(04h)
06-15(05h)
06-15(06h)
06-15(08h)
06-15(10h)
06-15(11h)
06-15(12h)
06-15(14h)
06-15(16h)
06-15(17h)
06-15(18h)
06-15(20h)
06-15(22h)
06-16(04h)
06-16(05h)
06-16(06h)
06-16(08h)
06-16(10h)
06-16(11h)
06-16(12h)
06-16(14h)
06-16(16h)
06-16(17h)
06-16(18h)
06-16(20h)
06-16(22h)
06-17(04h)
06-17(05h)
06-17(06h)
06-17(08h)
06-17(10h)
06-17(11h)
06-17(12h)
06-17(14h)
06-17(16h)
06-17(17h)
06-17(18h)
06-17(20h)
06-17(22h)

如此便可构建出表B

5.接下来对存储过程进行改造,将表A当作字符串放入存储过程,right join表B即可获取到预期结果

DROP PROCEDURE getrange3;
CREATE PROCEDURE getrange3 ( IN began date, IN eds date)
BEGIN
    declare leftsql text;
    declare sqlx text;
    set @leftsql = '';
    set @sqlx = '';
    set @leftsql = concat(@leftsql,"select u.date as 日期,
i.上限值 from 
(SELECT REPLACE
    ( h.日期, ':00', 'h' ) AS 日期,
    round( REPLACE ( format( h.上限值, 2 ), ',', '' ), 2 ) AS 上限值 
FROM
    (
SELECT
    concat( substr( g.日期, 6, 6 ), '(', g.时刻, ')' ) AS 日期,
    ( g.统调负荷 + g.东送负荷 - ( g.火电检修容量 - g.自备检修容量 ) * 0.5 * 0.9 - g.自备检修容量 * 0.85 * 0.9 ) AS 上限值 
FROM
    (
SELECT
    e.日期,
    e.时刻,
    e.统调负荷,
    e.东送负荷,
    f.自备检修容量,
    f.火电检修容量 
FROM
    (
SELECT
    a.日期,
    a.时刻,
    a.预测值 AS 统调负荷,
    b.预测值 AS 东送负荷 
FROM
    (
SELECT
    ( @ROW := @ROW + 1 ) AS 序号,
    businessTime AS 时刻,
    businessDate AS 日期,
    planValue AS 预测值 
FROM
    ( SELECT @ROW := 0 ) t,
    next_nified_dispatch_load_forecast 
WHERE
    businessDate >= '",began, 
    "' AND businessDate <='", eds ,
"'GROUP BY
    businessDate,
    businessTime 
ORDER BY
    ( @ROW := @ROW + 1 ) 
    ) a
    INNER JOIN (
SELECT
    ( @ROW := @ROW + 1 ) AS 序号,
    businessTime AS 时刻,
    businessDate AS 日期,
    planValue AS 预测值 
FROM
    ( SELECT @ROW := 0 ) t,
    next_eastward_ran_plan 
WHERE
    businessDate >= '",began, 
    "' AND businessDate <='", eds ,
"'GROUP BY
    businessDate,
    businessTime 
ORDER BY
    ( @ROW := @ROW + 1 ) 
    ) b ON a.日期 = b.日期 
    AND a.时刻 = b.时刻 
ORDER BY
    a.日期,
    a.时刻 
    ) e
    LEFT JOIN (
SELECT
    c.日期,
    c.自备检修容量,
    d.火电检修容量 
FROM
    (
SELECT
    ( @ROW := @ROW + 1 ) AS 序号,
    ( SELECT SUM( captive_capacity ) 自备总容量 FROM spot_base_data.t_node_capacity_common WHERE type = 1 ) - CAST( ROUND( SUM( capacity ), 3 ) AS DECIMAL ) 自备检修容量,
    businessDate AS 日期 
FROM
    ( SELECT @ROW := 0 ) t,
    maintenance_information_import 
WHERE
    businessDate >= '",began, 
    "' AND businessDate <='", eds ,
    "' AND equipment = '机组' 
    AND equipmentDispatchingName REGEXP 'xx|yy' 
GROUP BY
    businessDate 
ORDER BY
    ( @ROW := @ROW + 1 ) 
    ) c
    INNER JOIN (
SELECT
    ( @ROW := @ROW + 1 ) AS 序号,
    ( SELECT SUM( power_installation_capacity ) + SUM( captive_capacity ) 装机总容量 FROM spot_base_data.t_node_capacity_common WHERE type = 1 ) - CAST( ROUND( SUM( capacity ), 3 ) AS DECIMAL ) 火电检修容量,
    businessDate AS 日期 
FROM
    ( SELECT @ROW := 0 ) t,
    maintenance_information_import 
WHERE
    businessDate >= '",began, 
    "' AND businessDate <='", eds ,
    "' AND equipment = '机组' 
GROUP BY
    businessDate 
ORDER BY
    ( @ROW := @ROW + 1 ) 
    ) d ON c.日期 = d.日期 
    ) f ON f.日期 = e.日期 
    ) g 
    ) h 
WHERE
    日期 REGEXP '04:00|06:00|08:00|10:00|12:00|14:00|16:00|18:00|20:00|22:00|11:00|17:00|05:00') i");
    WHILE began <= eds 
        DO
        SET @sqlx = concat( @sqlx,'select  "', RIGHT ( began, 5 ), '(04h)', '"  as date union ' );
        SET @sqlx = concat( @sqlx,'select  "', RIGHT ( began, 5 ), '(05h)', '"  as date union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(06h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(08h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(10h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(11h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(12h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(14h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(16h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(17h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(18h)', '" as date  union ' );
        SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(20h)', '" as date  union ' );
        if began = eds then
            SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(22h)" as date');
        else
            SET @sqlx = concat( @sqlx, 'select  "', RIGHT ( began, 5 ), '(22h)', '" as date union ' );
        end if;
        SET began = adddate( began, 1 );
    END WHILE;
    set @leftsql = concat(@leftsql,' right join (',@sqlx,') u on i.日期=u.date');
    PREPARE stmt FROM @leftsql;
    EXECUTE stmt;
END;

调用和查询结果:

CALL getrange3 ('2022-06-07','2022-06-17' );

结果:

日期    上限值

06-07(04h) 12776.67
06-07(05h) 12782.67
06-07(06h) 13387.67
06-07(08h) 14223.27
06-07(10h) 15172.57
06-07(11h) 15562.17
06-07(12h) 14907.97
06-07(14h) 14273.77
06-07(16h) 14591.17
06-07(17h) 15226.17
06-07(18h) 15200.47
06-07(20h) 15762.37
06-07(22h) 15800.77
06-08(04h)
06-08(05h)
06-08(06h)
06-08(08h)
06-08(10h)
06-08(11h)
06-08(12h)
06-08(14h)
06-08(16h)
06-08(17h)
06-08(18h)
06-08(20h)
06-08(22h)
06-09(04h) 13330.37
06-09(05h) 13403.77
06-09(06h) 13882.47
06-09(08h) 14784.47
06-09(10h) 15672.77
06-09(11h) 16096.77
06-09(12h) 15407.07
06-09(14h) 14846.77
06-09(16h) 15237.47
06-09(17h) 15840.17
06-09(18h) 15751.07
06-09(20h) 16016.47
06-09(22h) 15933.47
06-10(04h)
06-10(05h)
06-10(06h)
06-10(08h)
06-10(10h)
06-10(11h)
06-10(12h)
06-10(14h)
06-10(16h)
06-10(17h)
06-10(18h)
06-10(20h)
06-10(22h)
06-11(04h)
06-11(05h)
06-11(06h)
06-11(08h)
06-11(10h)
06-11(11h)
06-11(12h)
06-11(14h)
06-11(16h)
06-11(17h)
06-11(18h)
06-11(20h)
06-11(22h)
06-12(04h)
06-12(05h)
06-12(06h)
06-12(08h)
06-12(10h)
06-12(11h)
06-12(12h)
06-12(14h)
06-12(16h)
06-12(17h)
06-12(18h)
06-12(20h)
06-12(22h)
06-13(04h)
06-13(05h)
06-13(06h)
06-13(08h)
06-13(10h)
06-13(11h)
06-13(12h)
06-13(14h)
06-13(16h)
06-13(17h)
06-13(18h)
06-13(20h)
06-13(22h)
06-14(04h)
06-14(05h)
06-14(06h)
06-14(08h)
06-14(10h)
06-14(11h)
06-14(12h)
06-14(14h)
06-14(16h)
06-14(17h)
06-14(18h)
06-14(20h)
06-14(22h)
06-15(04h)
06-15(05h)
06-15(06h)
06-15(08h)
06-15(10h)
06-15(11h)
06-15(12h)
06-15(14h)
06-15(16h)
06-15(17h)
06-15(18h)
06-15(20h)
06-15(22h)
06-16(04h)
06-16(05h)
06-16(06h)
06-16(08h)
06-16(10h)
06-16(11h)
06-16(12h)
06-16(14h)
06-16(16h)
06-16(17h)
06-16(18h)
06-16(20h)
06-16(22h)
06-17(04h)
06-17(05h)
06-17(06h)
06-17(08h)
06-17(10h)
06-17(11h)
06-17(12h)
06-17(14h)
06-17(16h)
06-17(17h)
06-17(18h)
06-17(20h)
06-17(22h)

ok,我们完成了动态补点,完美收工!!!

 

  • 添加到短语集
     
    • 没有此单词集:世界语 → 中文(简体)...
       
    • 创建新的单词集...
  • 拷贝
posted @ 2022-06-08 13:57  海的味道  阅读(207)  评论(0编辑  收藏  举报