15

指定された特定の年の Student テーブルから、男性、女性、および合計の学生を数えたいと思います。結果を次の形式で表示できればいいのにと思います。

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

指定された年に一致する男性/女性がない場合、クエリは 0 を表示する必要があります。どうすればこれを実現できますか?

前もって感謝します

4

13 に答える 13

24

次のクエリを検討してください。

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
;
于 2013-06-15T00:49:46.353 に答える
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
于 2014-10-26T11:03:05.573 に答える
2

グリッドの書式設定とデータの取得を混在させるべきではないため

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
于 2013-06-15T03:12:43.843 に答える
1

これは、学生テーブルを 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デモです。

于 2013-06-15T03:24:43.450 に答える
1

このようなもの:

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 )
于 2013-06-15T00:50:20.330 に答える
1

あなたの要求は非常に単純に見えますが、2 つの複雑な問題があります。1 つ目は、1 つの行が他の 2 つの行の要約であるということです。これは、クエリでrolluporを使用することを示唆しています。grouping sets

2 つ目は、データがない場合でも値が必要であるという要件です。これは、「ドライバー」サブクエリの使用を示唆しています。このようなサブクエリは、値を割り当てる前に、出力内のすべての行を定義します。でドライバー テーブルを使用しますleft outer join

記載されていない要件は、年を 1 回だけ言及することである場合があります。

クエリに対する次のアプローチは、その年の最終フォームをまとめます。次に左が要約に結合し、そこから値があればそれを引き出します。

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、データ内に呼び出される列があることを前提としています (サンプル入力またはテーブル形式がない場合、列名とサンプル値を推測する必要があります)。

于 2013-06-15T07:39:36.667 に答える
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
于 2013-06-20T10:10:29.480 に答える
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
于 2013-06-15T02:13:42.083 に答える
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
于 2015-07-27T07:22:39.870 に答える
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
于 2013-06-15T02:18:27.640 に答える
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;
于 2013-06-15T00:49:53.513 に答える
0

Gender または RegisteredYear に null がないと仮定して、これを試してください。

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
于 2013-06-15T00:53:28.213 に答える