【问题标题】:改进查询以提高写作效率
【发布时间】:2022-01-02 16:56:14
【问题描述】:

您将如何改进 SQL Server 中的以下查询以查找哪些课程中的男女比例超过 70%? (我添加了所有相关表格的图表......并非所有表格都是必需的)

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

我想练习有效且更短(更好)的查询。

谢谢大家!

【问题讨论】:

  • 为什么要将COUNTs 转换为float
  • 请提供表结构和示例数据作为SQL语句。 minimal reproducible example
  • 您可以一次有条件地统计男性、女性。

标签: sql sql-server aggregate-functions


【解决方案1】:

您可以使用单个查询,例如:

SELECT 
     c.CourseId, 
     COUNT(DISTINCT CASE WHEN s.Gender = 'F' THEN c.StudentId ELSE NULL END) AS Women,
     COUNT(DISTINCT CASE WHEN s.Gender = 'M' THEN c.StudentId ELSE NULL END) AS Man,
     CAST(COUNT(DISTINCT CASE WHEN s.Gender = 'M' THEN c.StudentId ELSE NULL END) AS FLOAT) / COUNT(DISTINCT c.StudentId) AS MensRate
FROM Classrooms c
INNER JOIN Students s ON c.StudentId = s.StudentId
GROUP BY c.CourseId
HAVING CAST(COUNT(DISTINCT CASE WHEN s.Gender = 'M' THEN c.StudentId ELSE NULL END) AS FLOAT) / COUNT(DISTINCT c.StudentId) > 0.7

MS SQL fiddle group by

意味着您应该将男士计数除以总计数以计算速率。

【讨论】:

  • 我添加了 AS FLOAT 这样我就不会因为回合而错过任何结果。谢谢!