CREATE OR REPLACE PROCEDURE pro_maintain_sum(p_cur_date varchar(50)) LANGUAGE plpgsql AS $$ DECLARE v_cur_date date := to_date(p_cur_date, 'YYYY-MM-DD'); v_last_date date := v_cur_date - interval '1 day'; v_last_week_start date := v_cur_date - interval '14 days'; v_last_week_end date := v_cur_date - interval '8 days'; v_last_month date := v_cur_date - interval '1 month'; v_last_year date := v_cur_date - interval '1 year'; day_num int; week_num int; month_num int; year_num int; last_day_num int; last_week_num int; last_month_num int; last_year_num int; day_p varchar(50); week_p varchar(50); month_p varchar(50); year_p varchar(50); all_day_num int; all_week_num int; all_month_num int; all_year_num int; all_last_day_num int; all_last_week_num int; all_last_month_num int; all_last_year_num int; v_building_id varchar(50); -- 楼栋编号(添加前缀避免冲突) BEGIN -- 处理各楼栋数据 FOR v_building_id IN SELECT DISTINCT id FROM building LOOP -- 历史数据查询 SELECT COUNT(*) INTO last_day_num FROM maintain_info WHERE building_id = building_id AND cur_date::date = v_last_date; SELECT COUNT(*) INTO last_week_num FROM maintain_info WHERE building_id = building_id AND cur_date::date BETWEEN v_last_week_start AND v_last_week_end; SELECT COUNT(*) INTO last_month_num FROM maintain_info WHERE building_id = building_id AND date_trunc('month', cur_date) = date_trunc('month', v_last_month); SELECT COUNT(*) INTO last_year_num FROM maintain_info WHERE building_id = building_id AND date_trunc('year', cur_date) = date_trunc('year', v_last_year); -- 当前数据查询 SELECT COUNT(*) INTO day_num FROM maintain_info WHERE building_id = building_id AND cur_date::date = v_cur_date; SELECT COUNT(*) INTO week_num FROM maintain_info WHERE building_id = building_id AND cur_date::date BETWEEN (v_cur_date - interval '6 days') AND v_cur_date; SELECT COUNT(*) INTO month_num FROM maintain_info WHERE building_id = building_id AND date_trunc('month', cur_date) = date_trunc('month', v_cur_date); SELECT COUNT(*) INTO year_num FROM maintain_info WHERE building_id = building_id AND date_trunc('year', cur_date) = date_trunc('year', v_cur_date); -- 计算百分比 day_p := calc_percentage(day_num, last_day_num); week_p := calc_percentage(week_num, last_week_num); month_p := calc_percentage(month_num, last_month_num); year_p := calc_percentage(year_num, last_year_num); -- 插入或更新(使用UPSERT) INSERT INTO maintain_sum AS ms (cur_date, building_id, day_num, day_p, week_num, week_p, month_num, month_p, year_num, year_p) VALUES (v_cur_date, building_id, day_num, day_p, week_num, week_p, month_num, month_p, year_num, year_p) ON CONFLICT (cur_date, building_id) DO UPDATE SET day_num = EXCLUDED.day_num, day_p = EXCLUDED.day_p, week_num = EXCLUDED.week_num, week_p = EXCLUDED.week_p, month_num = EXCLUDED.month_num, month_p = EXCLUDED.month_p, year_num = EXCLUDED.year_num, year_p = EXCLUDED.year_p; END LOOP; -- 处理所有楼栋汇总数据 SELECT COUNT(*) INTO all_last_day_num FROM maintain_info WHERE cur_date::date = v_last_date; SELECT COUNT(*) INTO all_last_week_num FROM maintain_info WHERE cur_date::date BETWEEN v_last_week_start AND v_last_week_end; SELECT COUNT(*) INTO all_last_month_num FROM maintain_info WHERE date_trunc('month', cur_date) = date_trunc('month', v_last_month); SELECT COUNT(*) INTO all_last_year_num FROM maintain_info WHERE date_trunc('year', cur_date) = date_trunc('year', v_last_year); SELECT COUNT(*) INTO all_day_num FROM maintain_info WHERE cur_date::date = v_cur_date; SELECT COUNT(*) INTO all_week_num FROM maintain_info WHERE cur_date::date BETWEEN (v_cur_date - interval '6 days') AND v_cur_date; SELECT COUNT(*) INTO all_month_num FROM maintain_info WHERE date_trunc('month', cur_date) = date_trunc('month', v_cur_date); SELECT COUNT(*) INTO all_year_num FROM maintain_info WHERE date_trunc('year', cur_date) = date_trunc('year', v_cur_date); -- 计算百分比(可复用函数) day_p := calc_percentage(all_day_num, all_last_day_num); week_p := calc_percentage(all_week_num, all_last_week_num); month_p := calc_percentage(all_month_num, all_last_month_num); year_p := calc_percentage(all_year_num, all_last_year_num); -- 使用UPSERT处理汇总数据 INSERT INTO maintain_sum AS ms (cur_date, building_id, day_num, day_p, week_num, week_p, month_num, month_p, year_num, year_p) VALUES (v_cur_date, '所有', all_day_num, day_p, all_week_num, week_p, all_month_num, month_p, all_year_num, year_p) ON CONFLICT (cur_date, building_id) DO UPDATE SET day_num = EXCLUDED.day_num, day_p = EXCLUDED.day_p, week_num = EXCLUDED.week_num, week_p = EXCLUDED.week_p, month_num = EXCLUDED.month_num, month_p = EXCLUDED.month_p, year_num = EXCLUDED.year_num, year_p = EXCLUDED.year_p; END; $$; -- 创建百分比计算函数 CREATE OR REPLACE FUNCTION calc_percentage(current_val int, last_val int) RETURNS varchar(50) AS $$ BEGIN RETURN CASE WHEN last_val > 0 THEN ROUND(((current_val - last_val)::numeric / last_val * 100)::numeric, 2) || '%' ELSE '0%' END; END; $$ LANGUAGE plpgsql;