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

SQL Server查询优化:如何高效查询男女比例超70%的课程

优化后SQL(通用版本,兼容学生重复选课的场景)

SELECT 
    CourseId,
    CAST(ROUND(CAST(Men AS FLOAT) / NULLIF(Women, 0) * 100, 2) AS NUMERIC(12,2)) AS Ratio
FROM (
    SELECT 
        c.CourseId,
        COUNT(DISTINCT CASE WHEN s.Gender = 'M' THEN c.StudentId END) AS Men,
        COUNT(DISTINCT CASE WHEN s.Gender = 'F' THEN c.StudentId END) AS Women
    FROM Classrooms c
    INNER JOIN Students s ON c.StudentId = s.StudentId
    GROUP BY c.CourseId
    HAVING COUNT(DISTINCT CASE WHEN s.Gender = 'M' THEN c.StudentId END) > 0
       AND COUNT(DISTINCT CASE WHEN s.Gender = 'F' THEN c.StudentId END) > 0
) AS CourseGenderStat
WHERE CAST(Men AS FLOAT) / Women * 100 > 70
ORDER BY CourseId

核心优化点

  • 单次表扫描替代两次子查询:原写法需要两次扫描Classrooms、Students表后再做关联,优化后仅需一次关联+一次分组计算,IO开销直接降低50%以上,数据量越大性能提升越明显。
  • 异常兼容:通过NULLIF和HAVING提前过滤无男生/无女生的课程,避免出现除以0的运行错误。
  • 无重复计算:比例仅需计算一次,无需在SELECT和WHERE子句中重复写计算逻辑。

更高性能版本(确认选课无重复记录时使用)

如果Classrooms表是选课表,同一个学生不会重复选同一门课,可以去掉COUNT中的DISTINCT,用SUM替代,性能会进一步提升:

SELECT 
    CourseId,
    CAST(ROUND(CAST(Men AS FLOAT) / Women * 100, 2) AS NUMERIC(12,2)) AS Ratio
FROM (
    SELECT 
        c.CourseId,
        SUM(CASE WHEN s.Gender = 'M' THEN 1 ELSE 0 END) AS Men,
        SUM(CASE WHEN s.Gender = 'F' THEN 1 ELSE 0 END) AS Women
    FROM Classrooms c
    INNER JOIN Students s ON c.StudentId = s.StudentId
    GROUP BY c.CourseId
    HAVING SUM(CASE WHEN s.Gender = 'M' THEN 1 ELSE 0 END) > 0
       AND SUM(CASE WHEN s.Gender = 'F' THEN 1 ELSE 0 END) > 0
) AS CourseGenderStat
WHERE CAST(Men AS FLOAT) / Women * 100 > 70
ORDER BY CourseId

索引优化建议

为了进一步提升查询性能,可以新增两个覆盖索引:

  • Students表新增联合索引 (StudentId, Gender),关联时无需回表查询性别字段
  • Classrooms表新增联合索引 (CourseId, StudentId),分组和关联操作可以直接走索引完成,无需访问堆表或聚集索引

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 07:54:08