You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL优化:用子查询替代连接简化学校支持时长统计查询

简化支持时长统计查询的方案

问题分析

你当前的方案需要为每个支持类型单独创建视图,再通过多表LEFT JOIN计算总时长,不仅重复劳动多,维护成本高,新增支持类型时还要修改多处代码。下面提供两种简化方案,重点满足你用子查询替代连接的需求,同时给出更具扩展性的优化方案。


方案一:用关联子查询替代视图与多表连接

无需创建任何视图,直接在SELECT子句中通过关联子查询计算每个支持类型的总时长,同时处理NULL值避免总和异常:

SELECT 
  sr.school_id,
  -- 每个支持类型的总时长通过关联子查询计算
  COALESCE((SELECT SUM(sr_inner.smt * st.support_days) 
            FROM support_record sr_inner
            CROSS JOIN support_type st 
            WHERE st.support_id = 'smt' AND sr_inner.school_id = sr.school_id), 0) AS smt_support_total,
  COALESCE((SELECT SUM(sr_inner.acs * st.support_days) 
            FROM support_record sr_inner
            CROSS JOIN support_type st 
            WHERE st.support_id = 'acs' AND sr_inner.school_id = sr.school_id), 0) AS acs_support_total,
  COALESCE((SELECT SUM(sr_inner.hds * st.support_days) 
            FROM support_record sr_inner
            CROSS JOIN support_type st 
            WHERE st.support_id = 'hds' AND sr_inner.school_id = sr.school_id), 0) AS hds_support_total,
  COALESCE((SELECT SUM(sr_inner.rau * st.support_days) 
            FROM support_record sr_inner
            CROSS JOIN support_type st 
            WHERE st.support_id = 'rau' AND sr_inner.school_id = sr.school_id), 0) AS rau_support_total,
  COALESCE((SELECT SUM(sr_inner.wau * st.support_days) 
            FROM support_record sr_inner
            CROSS JOIN support_type st 
            WHERE st.support_id = 'wau' AND sr_inner.school_id = sr.school_id), 0) AS wau_support_total,
  COALESCE((SELECT SUM(sr_inner.fds * st.support_days) 
            FROM support_record sr_inner
            CROSS JOIN support_type st 
            WHERE st.support_id = 'fds' AND sr_inner.school_id = sr.school_id), 0) AS fds_support_total,
  -- 总时长直接累加各子查询结果
  COALESCE((SELECT SUM(sr_inner.smt * st.support_days) FROM support_record sr_inner CROSS JOIN support_type st WHERE st.support_id = 'smt' AND sr_inner.school_id = sr.school_id), 0) +
  COALESCE((SELECT SUM(sr_inner.acs * st.support_days) FROM support_record sr_inner CROSS JOIN support_type st WHERE st.support_id = 'acs' AND sr_inner.school_id = sr.school_id), 0) +
  COALESCE((SELECT SUM(sr_inner.hds * st.support_days) FROM support_record sr_inner CROSS JOIN support_type st WHERE st.support_id = 'hds' AND sr_inner.school_id = sr.school_id), 0) +
  COALESCE((SELECT SUM(sr_inner.rau * st.support_days) FROM support_record sr_inner CROSS JOIN support_type st WHERE st.support_id = 'rau' AND sr_inner.school_id = sr.school_id), 0) +
  COALESCE((SELECT SUM(sr_inner.wau * st.support_days) FROM support_record sr_inner CROSS JOIN support_type st WHERE st.support_id = 'wau' AND sr_inner.school_id = sr.school_id), 0) +
  COALESCE((SELECT SUM(sr_inner.fds * st.support_days) FROM support_record sr_inner CROSS JOIN support_type st WHERE st.support_id = 'fds' AND sr_inner.school_id = sr.school_id), 0) AS support_days_total
FROM support_record sr
GROUP BY sr.school_id;

优点:

  • 无需创建和维护多个视图,代码集中在一个查询中
  • COALESCE函数处理无数据的情况,避免总和返回NULL

方案二:宽表转窄表+条件聚合(更具扩展性)

你的support_record是宽表结构(每个支持类型对应一列),先将其转换为窄表,再与support_type关联计算,最后用条件聚合转回宽表格式。这种方案新增支持类型时只需修改少量代码:

WITH unpivoted_support AS (
  -- 将宽表转换为窄表:每个学校-支持类型组合为一行
  SELECT school_id, 'smt' AS support_id, smt AS count FROM support_record
  UNION ALL
  SELECT school_id, 'acs' AS support_id, acs AS count FROM support_record
  UNION ALL
  SELECT school_id, 'hds' AS support_id, hds AS count FROM support_record
  UNION ALL
  SELECT school_id, 'rau' AS support_id, rau AS count FROM support_record
  UNION ALL
  SELECT school_id, 'wau' AS support_id, wau AS count FROM support_record
  UNION ALL
  SELECT school_id, 'fds' AS support_id, fds AS count FROM support_record
),
school_support_totals AS (
  -- 计算每个学校每种支持类型的总时长
  SELECT 
    us.school_id,
    us.support_id,
    SUM(us.count * st.support_days) AS support_total
  FROM unpivoted_support us
  JOIN support_type st ON us.support_id = st.support_id
  GROUP BY us.school_id, us.support_id
)
-- 条件聚合转回宽表,同时计算总时长
SELECT 
  school_id,
  MAX(CASE WHEN support_id = 'smt' THEN support_total END) AS smt_support_total,
  MAX(CASE WHEN support_id = 'acs' THEN support_total END) AS acs_support_total,
  MAX(CASE WHEN support_id = 'hds' THEN support_total END) AS hds_support_total,
  MAX(CASE WHEN support_id = 'rau' THEN support_total END) AS rau_support_total,
  MAX(CASE WHEN support_id = 'wau' THEN support_total END) AS wau_support_total,
  MAX(CASE WHEN support_id = 'fds' THEN support_total END) AS fds_support_total,
  SUM(support_total) AS support_days_total
FROM school_support_totals
GROUP BY school_id;

优点:

  • 扩展性强:新增支持类型时,只需在unpivoted_support的UNION ALL中添加一行,再在最后SELECT的CASE WHEN中对应新增一条即可
  • 避免重复子查询,数据量大时效率更高
  • 逻辑清晰,减少出错概率

内容的提问来源于stack exchange,提问作者cyal7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 08:35:03