SQL Server - 计算具有条件的列并输出百分比

时间:2014-06-03 18:28:32

标签: sql sql-server

我有现实世界的情况:

有“小屋”标识的小屋。人们可以住在小木屋里。 'person_age'表示每个人的年龄。

我试图找出每个小屋中有多少人住在35岁以上,并且该小屋中有多少人超过35岁,条件是我只想考虑搬进小屋的人特定的日期范围,我也想了解每个舱室的结果。

我有以下查询:

select
   [house]
  ,count(case when person_age > 35 then 1 end) as [older than 35]
  ,(cast(count(case when person_age > 35 then 1 end) as float))/(count(case when person_age > 35 then 1 else 1 end)) as [percent older than 35]
from cabins
where
  move_in_date >= '2014-02-01' 
  and move_in_date <= '2014-03-01'
group by [house]

有没有更好的方法来计算百分比字段,例如特定功能或其他什么?我认为它有效,但它太丑了。

我是否正确使用计数功能?它给了我我想要的东西,但我不确定。

4 个答案:

答案 0 :(得分:2)

您的查询在逻辑中看起来没问题。我会这样写:

select [house],
       sum(case when person_age > 35 then 1 else 0 end) as [older than 35],
       avg(case when person_age > 35 then cast(1 as float) else 0
           end) as [percent older than 35]
from cabins
where move_in_date >= '2014-02-01' and move_in_date <= '2014-03-01'
group by [house];

换句话说,您只需创建一个值为0.0或1.0的指标,并使用avg()函数。

答案 1 :(得分:2)

您选择了非聚合以及两个聚合,因此您需要GROUP BY,并且可以使用OVER()上的SUM()来获取Percent of total }:

SELECT  [house]
      , COUNT(CASE WHEN person_age > 35 THEN 1 END) AS [older than 35]
      , COUNT(CASE WHEN person_age > 35 THEN 1 END)*1.0/SUM(COUNT(CASE WHEN person_age > 35 THEN 1 END))OVER() AS [percent older than 35]
FROM    cabins
WHERE   move_in_date >= '2014-02-01'
        AND move_in_date <= '2014-03-01'
GROUP BY [house]

更新:重新阅读我想你想要每个房子超过35人的百分比,所以简单地说:

SELECT  [house]
      , COUNT(CASE WHEN person_age > 35 THEN 1 END) AS [older than 35]
      , COUNT(CASE WHEN person_age > 35 THEN 1 END)*1.0/COUNT(person_age) AS [percent older than 35]
FROM    cabins
WHERE   move_in_date >= '2014-02-01'
        AND move_in_date <= '2014-03-01'
GROUP BY [house]

答案 2 :(得分:1)

您的代码存在以下几个问题:

1)这些计数没有条件,所以他们会给你所有小屋中超过35人的总数和所有小屋中超过35人的百分比(而你想要的是每个小屋中的这些数字)。要解决此问题,您需要添加&#34; GROUP BY [house]&#34;在你的where子句之后。这将告诉聚合函数(计数和百分比)仅查看每行的给定房屋。

2)您不需要在百分比字段的分母中使用案例陈述。 Count(*)做同样的事情。它应该是这样的:

(cast(count(case when person_age > 35 then 1 end) as float))/(count(*)) as [percent older than 35]

编辑:count(1)正如@Darka在评论中建议的那样也行。

答案 3 :(得分:1)

你可以稍微简化一下

select
   [house]
  ,count(case when person_age > 35 then 1 end) as [older than 35]
  ,(cast(count(case when person_age > 35 then 1 end) as float))/(count(1)) as [percent older than 35]
from cabins
where
  move_in_date between '2014-02-01' and '2014-03-01'
GROUP BY [house]