3

各カテゴリの個人の数を数えて、この要約統計表を作成しようとしています

Agegroup   |    All    |    Female   |    Male
------------------------------------------------
All        |  560594   |    34324    |   234244
< 20       |   4324    |     545     |    3456
20 - 30    |  76766    |     3424    |   32428
30 - 40    |  36766    |     764     |   82427
40 - 50    |  46766    |     4324    |   72422
50 - 60    |  66766    |     3424    |   52424
> 60       |  76766    |    43424    |   12423

この表から

PersonID  |   Age   |  Sex   
----------------------------
  A      |    43    |   F
  B      |    22    |   F
  C      |    65    |   M
  D      |    33    |   F
  E      |    28    |   M

これはSQLで「一度に」可能ですか? これで実験しましたが、実際には一緒に来ていません..

SELECT SUM(CASE WHEN Age < 20 THEN 1 ELSE 0 END) AS [Under 20],
    SUM(CASE WHEN Age BETWEEN 20 AND 30 THEN 1 ELSE 0 END) AS [20-30],
    SUM(CASE WHEN Age BETWEEN 30 AND 40 THEN 1 ELSE 0 END) AS [30-40]
FROM Persons
4

5 に答える 5

4

以下がこれを達成する最も簡単な方法であり、その年齢層に人がいない場合でも列を取り戻すことができると思います. また、case 式の代わりにSex使用できる値が 2 つしかないためです。NULLIF

SELECT  [Agegroup] = Name,
        [All] = COUNT(Person.PersonID),
        [Female] = COUNT(NULLIF(Person.Sex, 'M')),
        [Male] = COUNT(NULLIF(Person.Sex, 'F'))
FROM    (VALUES 
            (0, 1000, 'All'),
            (0, 20, '< 20'),
            (20, 30, '20 - 30'),
            (30, 40, '30 - 40'),
            (40, 50, '40 - 40'),
            (50, 60, '50 - 40'),
            (60, 1000, '> 60')
        ) AgeRange (MinValue, MaxValue, Name)
        LEFT JOIN Person
            ON Person.Age >= AgeRange.MinValue
            AND Person.Age < AgeRange.Maxvalue
GROUP BY AgeRange.Name, AgeRange.MinValue, AgeRange.Maxvalue
ORDER BY AgeRange.MinValue, AgeRange.MaxValue DESC

SQL Fiddle の例

于 2012-10-31T09:22:46.990 に答える
2

多分このようなもの:

DECLARE @T TABLE(PersonID VARCHAR(5), Age INT,Sex VARCHAR(5))

INSERT INTO @T
VALUES
    ('A',43,'F'),
    ('B',22 ,'F'),
    ('C ',65,'M'),
    ('D',33,'F'),
    ('E',28,'M')

SQL

SELECT
    'All' AS Agegroup,
    COUNT(*) AS [All],
    SUM(CASE WHEN tbl.Sex='F' THEN 1 ELSE 0 END) AS Female,
    SUM(CASE WHEN tbl.Sex='M' THEN 1 ELSE 0 END) AS Male
FROM
    @T AS tbl
UNION ALL   
SELECT
    tbl.Agegroup,
    COUNT(*) AS [All],
    SUM(CASE WHEN tbl.Sex='F' THEN 1 ELSE 0 END) AS Female,
    SUM(CASE WHEN tbl.Sex='M' THEN 1 ELSE 0 END) AS Male
FROM
(
    SELECT
        (
            CASE 
            WHEN Age BETWEEN 0 and 20
            THEN '< 20'
            WHEN Age BETWEEN 20 and 30
            THEN '20 - 30'
            WHEN Age BETWEEN 30 and 40
            THEN '30 - 40'
            WHEN Age BETWEEN 40 and 50
            THEN '40 - 50'
            WHEN Age BETWEEN 50 and 60
            THEN '50 - 60'
            WHEN Age> 60
            THEN '> 60'
            END
        ) AS Agegroup,
        t.Age,
        t.Sex
    FROM
        @T AS t
) AS tbl
GROUP BY
    tbl.Agegroup
于 2012-10-31T08:57:34.017 に答える
2

最良のパターンは、年齢範囲テーブル (または以下の例のような仮想テーブル) を作成してそれに結合し、結果をピボットして結果を列形式にすることです。

select range as AgeGroup, m as Male, F as Female, m+f as [all]
from
(  
    select PersonID, range, sex  
    from
    (
        select 'all' as range, 0 as minval, 200 as maxval
        union select '<20',0,19
        union select '20-29',20,29
        -- etc....
    ) ranges
        left join
    yourtable t
        on t.age between minval and maxval
) src
pivot
    (count(personid) for sex in ([m],[f])) p
于 2012-10-31T09:00:08.337 に答える
1

これを試して:

;with Age_range as(
select '<20' as age union all
select '20 - 30' as age union all
select '30 - 40' as age union all
select '40 - 50' as age union all
select '50 - 60' as age union all
select '>60' as age  
),
cte as(
select [Sex],
sum(case when [Age]<20 then 1 else 0 end) as '<20' ,
sum(case when [Age]between 20 and 29 then 1 else 0 end) as '20 - 30',
sum(case when [Age]between 30 and 39 then 1 else 0 end) as '30 - 40',
sum(case when [Age]between 40 and 49 then 1 else 0 end) as '40 - 50',
sum(case when [Age]between 50 and 59 then 1 else 0 end) as '50 - 60',
sum(case when [Age]>=60 then 1 else 0 end) as '>60' 
 from Persons
 group by [Sex]),
 cte1 as(select Sex,'<20'  as cnt from cte where [<20]>0 union all
 select Sex,'20 - 30'  as cnt from cte where [20 - 30]>0 union all
 select Sex,'30 - 40'  as cnt from cte where [30 - 40]>0 union all
 select Sex,'40 - 50'  as cnt from cte where [40 - 50]>0 union all
 select Sex,'50 - 60'  as cnt from cte where [50 - 60]>0 union all
 select Sex,'>60'  as cnt from cte where [>60]>0)
 select A.age,
        COUNT(case when sex in ('M','F') then 1 end) as [All],
        COUNT(case when sex='F' then 1 end) as Female,
        COUNT(case when sex='M' then 1 end) as Male
  from Age_range A left join cte1 C
  on A.age=C.cnt
  group by A.age


SQL フィドルのデモ

于 2012-10-31T09:19:51.080 に答える
0
select  'All' as [Age Group]
.       count(*) as [All],
,       sum(case Sex when 'F' then 1 end) as Female
,       sum(case Sex when 'M' then 1 end) as Male
from    Persons
union all
select  '< 20' as [Age Group]
.       count(*) as [All],
,       sum(case Sex when 'F' then 1 end) as Female
,       sum(case Sex when 'M' then 1 end) as Male
from    Persons
where   Age < 20
union all
select  '20 - 30' as [Age Group]
.       count(*) as [All],
,       sum(case Sex when 'F' then 1 end) as Female
,       sum(case Sex when 'M' then 1 end) as Male
from    Persons
where   20 <= Age and Age < 30
union all
...
于 2012-10-31T08:43:25.903 に答える