我正在尝试创建此摘要统计信息表,计算每个类别中的个人数量
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
答案 0 :(得分:4)
我相信以下是实现这一目标的最简单方法,即使在该年龄段内没有人,也可以获得该行。此外,由于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
<强> Example on SQL Fiddle 强>
答案 1 :(得分: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
答案 2 :(得分: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
答案 3 :(得分: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
答案 4 :(得分: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
...