Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 统计男性、女性和总数_Sql_Sql Server - Fatal编程技术网

Sql 统计男性、女性和总数

Sql 统计男性、女性和总数,sql,sql-server,Sql,Sql Server,我想从学生表中统计特定年份的男性、女性和学生总数。我希望能将结果显示在以下表格中: ==================================== | Label | Value | Year | ==================================== | Male | 0 | 2013 | | Female | 23 | 2013 | | Total | 23 |

我想从学生表中统计特定年份的男性、女性和学生总数。我希望能将结果显示在以下表格中:

====================================
| Label    |  Value   |   Year     |
====================================
| Male     |   0      |   2013     |
| Female   |  23      |   2013     |
| Total    |  23      |   2013     |
====================================
如果指定年份没有男性/女性匹配,则查询应显示0。你知道我该怎么做吗


提前感谢

考虑以下问题:

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
;
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 )
您可以将此结果转换为所需的形式。如果要在查询中执行此操作,则可以按如下方式执行:

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
;
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 )
只需运行此查询

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;
大概是这样的:

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
;
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 )

尝试此操作,假设性别或RegisteredEAR中没有空值:

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

这是另一个变体,使用UNPIVOT。这一个专门搜索男性和女性,所以它没有我的另一个灵活,因为你需要硬编码每个性别。但它可能是最有效的

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

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

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
自从你


我相信这是你只需通过学生表一次就可以达到的效率。只需根据需要更改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和姓名的简单演示,因为它们与手头的问题无关。

您的请求似乎很简单,但有两个复杂之处。第一行是其他两行的摘要。这建议在查询中使用汇总集或分组集

第二个是即使没有数据也需要有值。这建议使用驱动程序子查询。这样的子查询在赋值之前定义输出中的所有行。使用具有左外部联接的驱动程序表

一个未说明的要求可能是只提及一次年份

下面的查询方法将年度的最终表单放在一起。然后左侧连接摘要,从中提取值(如果有):

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的列,没有样本输入或表格格式,人们必须猜测列名和样本值。

这对我来说很有效。但是,在没有数据的年份,它仍然无法显示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
你应使用:

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
从中选择* 选择年份,将*计算为总计,当性别为'M'时求和,然后选择1,否则0以男性结束, 当SEXT='F'然后1 else 0作为mytable中的女性结束时求和 其中年份=2013年 按性别、年份分组 unpivot 收入构成价值 男性、女性、总收入的收入构成类型

也许您可以提供DDL和您当前的查询?学生表id、名称、性别、Registeredear有许多不同的选项供您选择:难道您不喜欢SQL吗!谢谢你帮我熬过了周五晚上:p此查询将读取表三次,这是低效的。对于小表,这是一个很好的解决方案。只需查询响应即可。但是,当我把年份改为2014年,没有数据时,它不会有任何回报。我原以为是2014年| 0 | 0|0@aby计数函数将始终返回数字。如果没有满足where条件的数据,那么它将返回0。但是年份部分将是空的…@aby也许您可以使用coalesce函数和绑定变量,比如maxcoalesceRegisteredear,:inputYear。。。其中:input_year是您应该指定的绑定变量。我不确定SQL Server是如何使用bind变量的,但您应该知道。哦,表中每年都会有一个摘要。你想要一个具体的年份。要做到这一点,将AllYears替换为AllYears,选择2014作为RegisteredEarthAnks,您的解决方案非常接近。但我应该做些什么改变,以便在没有所选年份的数据时返回女性| 0 | 2014、男性| 0 | 2014、总计| 0 | 2014?啊,我之前在性别/年份计数上犯了同样的错误,如果没有,则返回“1”。我喜欢你的解释,但是你的实现有缺陷,我认为太复杂了。group by中的s子查询缺少年份,并且总计不正确地包括所有年份。外部联接条件driver.gender不存在,应为driver.label,且2013年与null年的总行将永远不匹配。有关更简单的工作查询,请参阅。@dbenham。当我翻阅答案时,我正在寻找一个有联合和汇总的答案,并且一定因为分组ses而错过了你的答案。似乎没有一个答案能够解决正确的问题,这就是为什么我回答了问题,然后试图简化答案,导致您注意到的问题。我适时地更新了您的答案,因为这是合适的方法。您可以通过添加解决方案的简短描述来改进您的答案。欢迎使用堆栈溢出。回答 这里的ng问题很好,但这只是一堆未格式化的代码。一个好的答案应该格式简洁,包括对其工作原理和如何解决原始问题的解释。一个如此古老的问题的答案和如此多的答案也应该为这个话题增添新的见解。请给出你的答案以改进它。