views:

39

answers:

3

Hello all,

I'm not an expert in SQL by any means, and am having a hard time getting the data I need from a query. I'm working with a single table, Journal_Entry, that has a number of columns. One column is Status_ID, which is a foreign key to a Status table with three values "Green", "Yellow", and "Red". Also, a journal entry is logged against a particular User (User_ID).

I'm trying to get the number of journal entries logged for each Status, as a percentage of the total number of journal entries logged by a particular user. So far I've got the following for a Status of 1, which is green (and I know this doesn't work):

SELECT  CAST((SELECT COUNT(Journal_Entry_ID) 
        FROM Journal_Entry 
        WHERE Status_ID = 1 AND User_ID = 3 / 
        SELECT COUNT(Journal_Entry_ID) 
        FROM Journal_Entry AND User_ID = 3)) AS FLOAT * 100

I need to continue the query for the other two status ID's, 2 and 3, and ideally would like to end with the selection of three columns as percentages, one for each Status: "Green_Percent", "Yellow_Percent", and "Red_Percent".

This is probably the most disjointed question I've ever asked, so I apologize for any lack of clarity. I'll be happy to clarify as necessary. Also, I'm using SQL Server 2005.

Thanks very much.

+2  A: 

Use:

  SELECT je.statusid,
         COUNT(*) AS num,
         (COUNT(*) / (SELECT COUNT(*)+.0
                       FROM JOURNAL_ENTRY) ) * 100
    FROM JOURNAL_ENTRY je
GROUP BY je.statusid

Then it's a matter of formatting the precision you want:

CAST(((COUNT(*) / (SELECT COUNT(*)+.0 FROM BCCAMPUS.dbo.COURSES_RFIP)) * 100)
     AS DECIMAL(4,2))

...will give two decimal places. Cast the result to INT if you don't want any decimal places.

You could use a CTE to minimize the duplication:

WITH cte AS (
   SELECT je.*
     FROM JOURNAL_ENTRY je
    WHERE je.user_id = 3)
  SELECT c.statusid,
         COUNT(*) AS num,
         (COUNT(*) / (SELECT COUNT(*)+.0
                       FROM cte) ) * 100
    FROM cte c
GROUP BY c.statusid
OMG Ponies
A: 

DECLARE @JournalEntry TABLE ( StatusID INT ); INSERT INTO @JournalEntry (StatusID) VALUES (1), (1),(1),(1),(1),(1),(1) ,(2), (2),(2),(2),(2),(2),(2) ,(3), (3),(3),(3),(3),(3),(3);

SELECT CAST(SUM(CASE WHEN StatusID = 1 THEN 1 ELSE 0 END) AS DECIMAL) / CAST(COUNT() AS DECIMAL) Green ,CAST(SUM(CASE WHEN StatusID = 2 THEN 1 ELSE 0 END) AS DECIMAL) / CAST(COUNT() AS DECIMAL) Yellow ,CAST(SUM(CASE WHEN StatusID = 3 THEN 1 ELSE 0 END) AS DECIMAL) / CAST(COUNT(*) AS DECIMAL) Blue FROM @JournalEntry;

Tom Groszko
A: 

This should work:

SELECT
    user_id,
    (CAST(SUM(CASE WHEN status_id = 1 THEN 1 ELSE 0 END) AS DECIMAL(6, 4))/COUNT(*)) * 100 AS pct_green,
    (CAST(SUM(CASE WHEN status_id = 2 THEN 1 ELSE 0 END) AS DECIMAL(6, 4))/COUNT(*)) * 100 AS pct_yellow,
    (CAST(SUM(CASE WHEN status_id = 3 THEN 1 ELSE 0 END) AS DECIMAL(6, 4))/COUNT(*)) * 100 AS pct_red
FROM
    Journal_Entry
WHERE
    user_id = 1
GROUP BY
    user_id

If you don't need the user_id returned then you could get rid of that and the GROUP BY clause as long as you're only ever returning data for one user (or you want the aggregates for all users in the WHERE clause). If you want it for each user then you can keep the GROUP BY and simply get rid of the WHERE clause.

Tom H.