COUNT 和 MAX/MIN 和(HAVING?)在一个查询/ AdventureWorks2017 任务中

COUNT and MAX/MIN and (HAVING?) in one query/ AdventureWorks2017 task

我在 AdventureWorks2017 DB 中有一个训练任务。任务如下: 我需要一份职位列表,其中女性工作的比例最少和最多。只考虑至少有 4 人工作的那些。

到目前为止,我的代码如下所示:

select a.JobTitle, AVG(ertek) as avg_women, COUNT(*) as sum_women
from
(select BusinessEntityID, JobTitle, Gender, CASE WHEN Gender = 'F' THEN 1.0 ELSE 0.0
END as ertek
from HumanResources.Employee) a
group by a.JobTitle

这会返回所有的职位名称、这些职位中女性的平均数以及职位中女性的总和。问题是我不能在查询中使用 MAX 和 MIN(也许我需要创建另一个子查询?)。我需要完成任务的最后一部分“只考虑至少有 4 人工作的那些”。 感谢您的帮助!

ER图:https://homel.vsb.cz/~dan11/ddj/AdventureWorks2008_db_diagram.pdf

一次满足这些需求,逐步构建您的解决方案。

运行您的查询在每增加一步后确认预期的结果!

步骤

  1. 仅限 4 人以上的职位:
    group by e.JobTitle having count(1) >= 4
  2. 按比例计算女性人数(我将其解释为“一个职位中女性的相对人数”)。这需要总计,女性只计:
    count(1) as JobTitleCount
    count(case when e.Gender = 'F' then 1 end) as FemaleCount
    相对(比例)数或百分比则变为:
    count(case when e.Gender = 'F' then 1 end)*100.0/count(1) as FemalePercentage
  3. “最少”和“最多”表示 ranking functions 带有 order by 子句:
    dense_rank() over(order by <此处显示第 2 步的百分比> ) as RankLeast
    dense_rank() over(order by <此处显示第 2 步的百分比> desc) as RankMost
  4. 过滤任一排名第一的职位:
    where jfpr.RankLeast = 1 or jfpr.RankMost = 1

中间结果

步骤 1. 到 3.

select  e.JobTitle,
        count(1) as JobTitleCount,
        count(case when e.Gender = 'F' then 1 end) as FemaleCount,
        count(case when e.Gender = 'F' then 1 end)*100.0/count(1) as FemalePercentage,
        dense_rank() over(order by count(case when e.Gender = 'F' then 1 end)*100.0/count(1)     ) as FemalePercentageRankLeast,
        dense_rank() over(order by count(case when e.Gender = 'F' then 1 end)*100.0/count(1) desc) as FemalePercentageRankMost
from HumanResources.Employee e
group by e.JobTitle
having count(1) >= 4
order by FemalePercentage;

完整解决方案

将整个先前的查询移动到子查询 jfpr 中,并省略最终结果不再需要的列(JobTitleCountFemaleCount)。 order by 移到子查询之外。

select  jfpr.JobTitle,
        jfpr.FemalePercentage
from (  select  e.JobTitle,
                count(case when e.Gender = 'F' then 1 end)*100.0/count(1) as FemalePercentage,
                dense_rank() over(order by count(case when e.Gender = 'F' then 1 end)*100.0/count(1)     ) as FemalePercentageRankLeast,
                dense_rank() over(order by count(case when e.Gender = 'F' then 1 end)*100.0/count(1) desc) as FemalePercentageRankMost
        from HumanResources.Employee e
        group by e.JobTitle
        having count(1) >= 4 ) jfpr -- job female percentage rank
where jfpr.FemalePercentageRankLeast = 1
   or jfpr.FemalePercentageRankMost = 1
order by jfpr.FemalePercentage;

结果

在我的 AdventureWorks 副本上(不知道我现在有什么版本)这会产生:

JobTitle                      FemalePercentage
----------------------------  ----------------
Quality Assurance Technician   0.000000000000
Scheduling Assistant           0.000000000000
Janitor                       50.000000000000
Application Specialist        50.000000000000