SQL: Having trouble with query that gets percentages using aggregate functions

你说的曾经没有我的故事 提交于 2020-01-06 05:25:11

问题


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.


回答1:


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



回答2:


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.




回答3:


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;


来源:https://stackoverflow.com/questions/3462400/sql-having-trouble-with-query-that-gets-percentages-using-aggregate-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!