2014-06-03 6 views
0

У меня есть ситуации реального мира:SQL Server - счетные столбец с условиями, а также outputing проценты

Есть каюты, которые были определены «дом». Люди могут жить в каютах. «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] 

Есть ли лучший способ вычислить процентное поле, например, определенная функция или что-то? Это работает, я думаю, но это так уродливо.

Я использую функцию count правильно? Мне кажется, что я хочу, но я не уверен.

+1

'count (case when person_age> 35 then 1 else 1 end)' this part может быть 'count (1)' – Darka

+1

Я предполагаю, что у вас есть предложение GROUP BY, в противном случае утверждение не будет даже компиляции. – brazilianldsjaguar

+0

Гоша, ты прав. По какой-то причине это не так. – user38858

ответ

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().

+0

Я полностью забыл о функции avg(), когда написал свой ответ, но на ваш ответ (а также на вопрос) отсутствует предложение GROUP BY. – BryPie

+0

@BryPie. , , Хорошая точка зрения. Я добавил его. Спасибо. –

1

Несколько проблем с кодом:

1) эти счетчики не имеют никаких условий, поэтому они дадут вам общее количество людей старше 35 лет во всех каютах и ​​процент людей старше 35 лет во всех каютах (а то, что вы хотите, это эти цифры в КАЖДОЙ кабине). Чтобы исправить это, вам нужно добавить «GROUP BY [house]» после предложения where. Это покажет совокупные функции (количество и процент), чтобы смотреть только на данный дом для каждой строки.

2) Вам не нужен оператор case в знаменателе вашего поля процента. Граф (*) делает то же самое. Это должно выглядеть так:

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

Редактировать: count (1) как @Darka предлагает в комментариях также работать.

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] 

Update: Перечитывая I думаю, что вы хотите, процент людей старше 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] 
+0

К тому моменту, когда я увидел ваш комментарий, вы отредактировали свой ответ! Я проигнорировал, потому что вы опубликовали код без объяснений. Изменено, чтобы повысить, потому что вы добавили хорошее объяснение. – BryPie

+0

Да, я отредактировал вопрос с предложением 'group by', которое почему-то было упущено. – user38858

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] 
+0

В вашем ответе (а также в исходном вопросе) отсутствует предложение «group by». – BryPie

+0

Я положил 'group by' обратно. – user38858

+0

Будет ли' count (1) 'также считаться, когда поле' null '? (Это то, что я хотел бы.) Кроме того, я заметил, что вы положили 'count (1)' where Goat put 'count (person_age)'. Будут ли они все еще считать одни и те же части? – user38858

Смежные вопросы