views:

58

answers:

3

I've made a post here a link , asking some question about how to make statistics for number of users with from same age group so i can show pie chart. I want to take query in older post to higher level with percentages along with values...

Means i to have count(userID) of certain age group / count(userID) of all * 100 to get percentage. While i want to get results with 10% or more all others should be listed as others with their total percentage.

This initial query made by Martin Smith

With Ages As
(
select count(userID) ageCount,userBirthYear 
from Users
group by userBirthYear
)

SELECT ageCount,userBirthYear FROM Ages WHERE ageCount>5
UNION ALL
SELECT sum(ageCount) ,'others' As userBirthYear FROM Ages WHERE ageCount<=5

thanks

A: 

Enhancing my answer from the previous question:

DECLARE @UserCount int
SET @UserCount = (SELECT COUNT(*) FROM Users)

SELECT 
  SUM(sub.ageCount) as ageCount, 
  sub.userBirthYear,
  100 * SUM(sub.ageCount) / nullif(@UserCount,0) as Percent
FROM 
( 
  SELECT Count(userId) ageCount, 
    CASE WHEN COUNT(userID) * 10 >= @UserCount
         THEN userBirthYear 
         ELSE 'Other'
    END as userBirthYear 
  FROM Users 
  GROUP BY userBirthYear 
) as sub 
GROUP BY sub.userBirthYear
ORDER BY 1 desc
David B
@David B, 18K is not enough!
eugeneK
Doesn't work, ageCount userBirthYear Percent----------- ------------- -----------146 Other 1
eugeneK
Sure it did, those results indicate none of your userBirthYears had 10% of the total (so they all were grouped into Other). Try replacing *10 with *100 to move the minimum percent to 1% to see more results.
David B
It doesn't show Percent at all
eugeneK
moreover you have an error in query you have one too much ")" after second appearance of "@UserCount"
eugeneK
ok, fixed the stray paren, and multiplied the percent by 100 so it appears according to non-technical expectations.
David B
@David B, ok thanks. Just one issue is unsolved. * 10 in your original query does not limit to 10% but to 10 users in count(). I need limitation by percentage.
eugeneK
Go. Learn. Percentages.
David B
@David B, I've made previous statement judging by results i've got running your query not by reading it. So your sarcasm is pointless.
eugeneK
It's not sarcasm, I'm serious. You really needed me to multiply by 100 to know that a percent was computed? You can't tell how the WHEN clause is supposed to work, or how to change its behavior? I thought you asked for sql help, not third grade education. I was tempted to walk away from your questions as soon as I learned you store "BirthYear" as a string. That'll teach me.
David B
Even if you think my question is dumb or is of 3rd grader, you could simply help me with that. You query doesn't give results i've asked for. This is the issue not my understanding in percents which is irrelevant in this case.
eugeneK
+1  A: 

This would work

WITH Ages AS (
    select  COUNT(userID) as agecount, (count(userID)*100/(SELECT   SUM(agecount) FROM 
    (select count(userID) ageCount,userBirthYear  
    from    Users 
    group   by userBirthYear )B)) percentage, userBirthYear  
    from    Users 
    group   by userBirthYear )

    SELECT  userBirthYear, agecount, Percentage FROM Ages WHERE Percentage > 10
    UNION
    SELECT  'OTHERS',sum(agecount), sum(Percentage) FROM Ages WHERE Percentage <= 10
Baaju
Doesn't work, Doesn't work, ageCount userBirthYear Percent----------- ------------- -----------146 Other 1
eugeneK
What was your output ? Just to get the question here, is it to show only the age group that count for more than 10% of the total age group ? right say if you have a 12 2000's and a 1 1985 and 1 1986 ... you shud get 85 odd % for 2000 and Others 14 odd % ....
Baaju
@Baaju, if i set percentage at threshold of 5% for both. i get 5 rows back, when i sum percentage from all rows i get 85% total while it should be 100%.
eugeneK
@Eugene, Can you provide the table data and the expected output please ? Here i get a total of 100%
Baaju
It seems to work @ my end !
Baaju
+1  A: 

A straightforward way but requires two queries. Tested and seems to work...

DECLARE @NumUsers   INTEGER
SELECT  @NumUsers   = COUNT (userId)    FROM    Users


SELECT
    SUM (CntByYear.ageCount)                AS ageCount,
    SUM (CntByYear.agePercent)              AS agePercent,
    CntByYear.userBirthYear
FROM
    (
        SELECT
            COUNT (u.userId)                        AS ageCount,
            COUNT (u.userId) * 100.0 / @NumUsers    AS agePercent,
            CASE
                WHEN
                    COUNT (u.userId) * 100.0 / @NumUsers >= 10
                THEN
                    CAST (u.userBirthYear AS varchar)
                ELSE
                    'Other'
            END AS userBirthYear
        FROM
            Users   u
        GROUP BY
            u.userBirthYear
    ) AS CntByYear
GROUP BY
    CntByYear.userBirthYear
ORDER BY
    ageCount DESC,
    CntByYear.userBirthYear
Brock Adams
@Brock Adams,Msg 8127, Level 16, State 1, Line 34Column "CntByYear.ageCount" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.
eugeneK
Weird, it worked for me. Anyway, I've added it to the group clause, above.
Brock Adams
No, it doesn't work. gives me strange results all labeled with "others"
eugeneK
Something's not adding up. I get correct results every time on random data. What are your EXACT results? Perhaps your data has most years below the 10% threshold? Please post the results to pastebin.com. Also, please post the values of `userId` and `userBirthYear` to pastebin.com.
Brock Adams
Also, try the latest edit of the code, above. And, what version of SQL server are you on?
Brock Adams
@Brock Adams, mate i don't know what have you edited 8 minutes ago but your query works now.thanks
eugeneK
Glad it finally worked out.
Brock Adams