计算男性,女性和总数

时间:2013-06-15 00:41:49

标签: sql sql-server

我想计算学生表中指定特定年份的男,女,全学生人数。我希望结果能够以下列形式显示:

====================================
| Label    |  Value   |   Year     |
====================================
| Male     |   0      |   2013     |
| Female   |  23      |   2013     |
| Total    |  23      |   2013     |
====================================

如果指定年份没有男性/女性匹配,则查询应显示0。知道如何才能实现这一目标吗?

提前致谢

13 个答案:

答案 0 :(得分:12)

考虑以下问题:

select
  max(registeredYear) as year,
  count(case when gender='Male' then 1 end) as male_cnt,
  count(case when gender='Female' then 1 end) as female_cnt,
  count(*) as total_cnt
from student
where registeredYear = 2013
group by registeredYear;

结果如下:

Year male_cnt female_cnt total_cnt
---- -------- ---------- ---------
2013        0         23        23

您可以将此结果转换为所需的表单。如果您想在查询中执行此操作,则可以这样执行:

with t as (
    select
      max(registeredYear) as year,
      count(case when gender='Male' then 1 end) as male_cnt,
      count(case when gender='Female' then 1 end) as female_cnt,
      count(*) as total_cnt
    from student
    where registeredYear = 2013
    group by registeredYear)
select 'Male', male_cnt as male, year from t
union all
select 'Female', female_cnt as male, year from t
union all
select 'Total', total_cnt as male, year from t
;

答案 1 :(得分:5)

您应该使用:

select name, COUNT(*)as tot, 
  COUNT(case when details.gender='male' then 1 end) as male,
  COUNT(case when details.gender='female' then 1 end) as female 
  from details  group by name

答案 2 :(得分:1)

shouldn't mix grid formatting with data retrieval

以来
SELECT
  SUM(CASE WHEN gender = 'Male' THEN 1 ELSE 0 END) as MaleCount,
  SUM(CASE WHEN gender = 'Female' THEN 1 ELSE 0 END) as FemaleCount,
  COUNT(*) as TotalCount
FROM student
WHERE registeredYear = 2013

答案 3 :(得分:1)

我相信只需通过学生表一次就可以获得这样的效率。只需根据需要更改年度CTE。

with
year as 
(
  select '2013' year
),
gender as (
  select 'Male' gender
  union all
  select 'Female' gender
)
select coalesce(g.gender,'Total') "Label", 
       count(s.gender) "Value", 
       y.year "Year"
  from gender g
  cross join year y
  left join student s
    on s.gender = g.gender
   and s.year = y.year
 group by grouping sets( (g.gender, y.year), (y.year) )
 order by case g.gender when 'Male' then 1 when 'Female' then 2 else 3 end
;

完全标准化的数据模型可能同时具有学年和性别表,因此不需要CTE。 (除非你真的想要返回没有任何数据的年份的行)

这是一个没有学生ID和姓名的简单sqlfiddle演示,因为它们与手头的问题无关。

答案 4 :(得分:1)

您的要求似乎很简单,但它有两个并发症。首先是一行是另外两行的摘要。这表示在查询中使用rollupgrouping sets

第二个是即使没有数据也要求拥有值。这表明使用"驱动程序"子查询。这样的子查询在分配值之前定义输出中的所有行。您使用带有left outer join的驱动程序表。

未说明的要求可能只是提及一年。

以下查询方法将最终表单放在一起。然后左边加入摘要,从那里拉取值,如果有的话:

with year as (
      select 2013 as Year
     )
select driver.label, coalesce(s.value, 0) as Value, driver.Year
from ((select 'Male' as label, year from year
      ) union all
      (select 'Female' as label, year from year
      ) union all
      (select 'Total' as label, year from year
      )
     ) driver left outer join
     (select coalesce(Gender, 'Total') as Gender, year.year, count(*) as value
      from Students cross join year
      group by Gender with Rollup
     ) s
     on driver.year = s.year;

这假设性别被表示为"男性"和"女性"并且数据中有一个名为year的列(没有样本输入或表格格式,必须猜测列名和样本值)。

答案 5 :(得分:0)

只需运行此查询...

SELECT 
     MAX(registeredYear) as Year
    ,SUM(CASE WHEN gender = 'Male' THEN 1 END) AS Male
    ,SUM(CASE WHEN gender = 'Female' THEN 1 END) AS Female
    ,SUM(CASE WHEN gender IS NOT NULL THEN 1 ELSE 0 END) AS Total
 FROM from student
 WHERE registeredYear = 2013
 GROUP BY registeredYear;

答案 6 :(得分:0)

类似的东西:

select 'Male' as Label, count(gender) as Value from student where gender= 'Male'
union (
select 'Female' as Label, count(gender) as Value from student where gender= 'Female' )
union (
select 'Total' as Label, count(gender) as Value from student )

答案 7 :(得分:0)

尝试这一点,假设在Gender或RegisteredYear中没有空值:

WITH AllYears AS
(
   SELECT RegisteredYear
   FROM Student
   GROUP BY RegisteredYear
)

, AllGenders AS
(
   SELECT Gender
   FROM Student
   GROUP BY Gender
)    

, AllGendersAndYears AS
(
   SELECT Gender, RegisteredYear
   FROM AllGenders, AllYears
)

SELECT Gender, RegisteredYear, CountForGenderAndYear
FROM AllGendersAndYears 
   CROSS APPLY 
   (
      SELECT COUNT(*) AS CountForGenderAndYear
      FROM Student
      WHERE Student.Gender = AllGendersAndYears.Gender
         AND Student.RegisteredYear = AllGendersAndYears.RegisteredYear
   ) countForGenderAndYear

UNION ALL

SELECT 'Total', AllYears.RegisteredYear, CountForYear
FROM AllYears
   CROSS APPLY 
   (
      SELECT COUNT(*) AS CountForYear
      FROM Student
      WHERE Student.RegisteredYear = AllYears.RegisteredYear
   ) countForYear

答案 8 :(得分:0)

这是使用UNPIVOT的另一种变体。这个只专门搜索MALE和FEMALE,因此它不像我的另一个那样灵活(因为你需要对每个性别进行硬编码)。但它可能是效率最高的。

WITH AllYears (RegisteredYear) AS
(
    --SELECT DISTINCT RegisteredYear
    --FROM Student

     --...OR...

    SELECT 2014
)
, GenderAndYearCounts AS
(
    SELECT RegisteredYear
        , SUM(CASE Gender WHEN 'MALE' THEN 1 ELSE 0 END) MaleCount
        , SUM(CASE Gender WHEN 'FEMALE' THEN 1 ELSE 0 END) FemaleCount
        , COUNT(*) YearCount
    FROM Student
    GROUP BY RegisteredYear
)
, GenderAndYearCountsForAllYears AS
(
    SELECT AllYears.RegisteredYear
        , ISNULL(MaleCount, 0) AS MaleCount
        , ISNULL(FemaleCount, 0) AS FemaleCount
        , ISNULL(YearCount, 0) AS YearCount
    FROM AllYears
        LEFT JOIN GenderAndYearCounts ON GenderAndYearCounts.RegisteredYear = AllYears.RegisteredYear
)

SELECT Label, Value, RegisteredYear
FROM 
(
    SELECT RegisteredYear, MaleCount AS Male, FemaleCount AS Female, YearCount AS Total
    FROM GenderAndYearCountsForAllYears
) allCounts

UNPIVOT
(
    Value FOR Label IN (Male, Female, Total)
) unpivotted

答案 9 :(得分:0)

所有性别,然后是所有年份,然后是计数:

declare @Year int
set @Year = 2014

select labels.label,
    counts.cnt,
    @Year as registeredYear
    from 
        (select 'Male' as label, 1 as sortOrder
        union all 
        select 'Female', 2
        union all
        select 'All', 3) as labels 
   left join
       (select gender, 
        count(1) cnt
        from student
        where registeredYear = @Year
        group by gender) as counts
    on labels.label = counts.gender     
    order by labels.sortOrder

答案 10 :(得分:0)

这对我有用。但是,在没有数据的情况下,M和F仍然无法显示0:

Select * from 
(
SELECT isnull (SUM(CASE WHEN gender = 'M' THEN 1 ELSE 0 END),0) as Male,
       isnull(SUM(CASE WHEN gender = 'F' THEN 1 ELSE 0 END),0) as Female,
       registeredYear as 'year'

FROM student
WHERE registeredDate.Year = 2013 //could be a variable
group by registeredYear
 ) as s

 UNPIVOT
 ( 
value FOR gender IN (Male, Female) 
 ) Sub

答案 11 :(得分:0)

select sp.CLASS_Name , count(*) as total 
     , sum( case when si.STDNT_GENDER = 1   then 1 else 0 end )    as Male
     , sum( case when si.STDNT_GENDER = 0   then 1 else 0 end )    as Female
  from SCHOOL_PLANE sp  inner join STUDENT_INFO si 
on  sp.CLASS_ID=si.STDNT_CLASS_PLANE_ID group by sp.CLASS_Name

-------
select sp.CLASS_Name , count(*) as total 
     , sum( case si.STDNT_GENDER  when  1   then 1 else 0 end )    as Male
     , sum( case si.STDNT_GENDER  when  0   then 1 else 0 end )    as Female
  from SCHOOL_PLANE sp  inner join STUDENT_INFO si 
on  sp.CLASS_ID=si.STDNT_CLASS_PLANE_ID group by sp.CLASS_Name
------------
select sp.CLASS_Name , count(*) as total 
     , count( case when si.STDNT_GENDER = 1   then 1  end )    as Male
     , count( case when si.STDNT_GENDER = 0   then 1  end )    as Female
  from SCHOOL_PLANE sp  inner join STUDENT_INFO si 
on  sp.CLASS_ID=si.STDNT_CLASS_PLANE_ID group by sp.CLASS_Name

答案 12 :(得分:0)

从*中选择* (选择年,将count(*)作为总数,求和(当性别='M'时为1,否则0结尾的情况)为男性, mytable中的女性的总和(当性别='F'然后1否则0结束的情况) 年份= 2013 按性别分组,年份)
枢纽        (income_component_value          为(male,female,total)中的income_component_type        )