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.
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
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.
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;