SQL - Calculate percentage of multiple counts - mysql

I wrote a query to count and group all items in db by it's status.
Now, I need to calculate percentage of every given result.
SELECT
COUNT(CASE WHEN status='Pending' THEN 1 ELSE NULL END) as 'Pennding Requests',
COUNT(CASE WHEN status='Accepted' THEN 1 ELSE NULL END) as 'Accepted Requests',
COUNT(CASE WHEN status='Denied' THEN 1 ELSE NULL END) as 'Denied Requests'
FROM meeting_request;
which gave me:
enter image description here
I tried something like:
100.0 * (id / Pennding Requests) AS PERCENTAGE
Can some one suggest how to calculate percentage all of three status.

You can use AVG():
SELECT AVG( status = 'Pending' ) as pending_requests,
AVG( status = 'Accepted' ) as Accepted_Requests,
AVG( status = 'Denied' ) as Denied_Requests
FROM meeting_request;
Because MySQL interprets booleans as numbers with 1 for true and 0 for false, you can use the handy shortcut. The more formal SQL code is:
SELECT AVG(CASE WHEN status = 'Pending' THEN 1.0 ELSE 0 END)

Have you tried doing it like this?
SELECT
COUNT(CASE WHEN status='Pending' THEN 1 ELSE NULL END) / SUM(1) * 100.0 as 'Pennding Requests Percent',
COUNT(CASE WHEN status='Accepted' THEN 1 ELSE NULL END) / SUM(1) * 100.0 as 'Accepted Requests Percent',
COUNT(CASE WHEN status='Denied' THEN 1 ELSE NULL END) / SUM(1) * 100.0 as 'Denied Requests Percent'
FROM meeting_request;

Related

Can I get average of a column in mySQL DB based upon value of other column in one query?

I have a table of phone call activity for a client. In the table, I have one column for the length of the call (in seconds), and another column for "first time call" (true / false). I was hoping to find a way to get the average call length of first time calls separated from the average time of non first time calls? Is this doable in a singe mySQL query?
SELECT location,
count(*) AS total,
sum(case when firstCall = 'true' then 1 else 0 end) AS firstCall,
sum(case when answered = 'Yes' then 1 else 0 end) AS answered,
sum(case when tags like '%Lead%' then 1 else 0 end) as lead,
sum(case when tags like '%arbage%' then 1 else 0 end) as garbage,
avg(case when duration........firstTime = True???)
FROM staging
GROUP BY location
SELECT location,
count(*) AS total,
sum(case when firstCall = 'true' then 1 else 0 end) AS firstCall,
sum(case when answered = 'Yes' then 1 else 0 end) AS answered,
sum(case when tags like '%Lead%' then 1 else 0 end) as lead,
sum(case when tags like '%arbage%' then 1 else 0 end) as garbage,
sum(case when firstCall='true' then duration else 0 end)/sum(case when firstCall = 'true' then 1 else 0 end) as first_call_true_average,
sum(case when firstCall='false' then duration else 0 end)/sum(case when firstCall = 'false' then 1 else 0 end) as first_call_false_average
FROM staging
GROUP BY location
I would phrase this as:
select
location,
count(*) as total,
sum(firstcall = 'true' ) as cnt_firstcall,
sum(answered = 'Yes' ) as cnt_answered,
sum(tags like '%Lead%' ) as cnt_lead,
sum(tags like '%arbage%') as cnt_garbage,
avg(case when firstcall = 'true' then duration end) as avg_first_call,_duration
avg(case when firstcall = 'false' then duration end) as avg_non_first_call_duration
from staging
group by location
Rationale:
MySQL interpret true/false conditions as 1/0 values in numeric context, which greatly shortens the conditional sum()s
avg() ignores null values, so a simple case expression is sufficient to compute the conditional averages

Struggling with Pivot synta

Hi can someone tell me what is the error in this sample pivot command
SELECT *
FROM
(
SELECT *
FROM issued
) Src
PIVOT
( SUM(quantity)
FOR team IN (production,wastage,staff)
) AS Pvt;
I would do conditional aggregation instead :
select col,
sum(case when team = 'Production' then qty else 0 end) as production_qty,
sum(case when team = 'wastage' then qty else 0 end) as wastage_qty,
sum(case when team = 'staff' then qty else 0 end) as staff_qty
from issued
group by col --- use actual column name if any

Count different values in a column, while doing total and group by different column values

We have a table with data from different nodes and one of the column will have status report as "compliant or non-compliant", sample data as below
I want to filter the table in such a way that if any of the checks on a node shows non compliant, it should be flagged as non-compliant and rest as compliant. Using below query i am able to do it
SELECT COUNT(*) AS total_nodes,
SUM(fully_compliant = 0) AS Non_compliant_nodes,
SUM(fully_compliant = 1) AS compliant_nodes
FROM (
SELECT Node, CASE WHEN SUM(Status = 'Compliant') = COUNT(*) THEN 1 ELSE 0 END AS fully_compliant
FROM your_table GROUP BY Node
)
Now, i want to group and split the result by dept as below, how can i achieve this
I think you're looking for this:
select dept,
count(*) as total_nodes,
sum(case when non_compliant_chk = 0 then 1 else 0 end) as compliant_nodes,
sum(case when non_compliant_chk > 0 then 1 else 0 end) as non_compliant_nodes
from (
select dept,
node,
sum(case when 'Non-Compliant' then 1 else 0 end) as non_compliant_chk
from your_table
group by dept,
node
) v
group by dept;
With few modifications to what Brian suggested, I am able to get the desired result
select dept,
count(*) as total_nodes,
sum(case when non_compliant_chk = 0 then 1 else 0 end) as compliant_nodes,
sum(case when non_compliant_chk > 0 then 1 else 0 end) as non_compliant_nodes
from (
select dept,
node,
COUNT(CASE WHEN Compliance-Status = 'Non-Compliant' THEN 1 END) 'non_compliant_chk'
from table WHERE DOR >= DATE(NOW()) - INTERVAL 7 DAY
group by Dept,
Node
) v
group by Dept;

Invalid use of group function (For using count in select)

I got an error output on my sql query with remarks " Invalid use of group function "
This is my query
SELECT * FROM
(SELECT project,tbl_nif.POno,tbl_custmon.so, tbl_nif.matcode, tbl_nif.prodesc,
COUNT(CASE WHEN WEEK(MAX(plannedGI))+1=6 THEN 1 ELSE NULL END) as `week 6`,
COUNT(CASE WHEN WEEK(MAX(plannedGI))+1=2 THEN 1 ELSE NULL END) as `week 2`,
COUNT(CASE WHEN WEEK(MAX(plannedGI))+1=3 THEN 1 ELSE NULL END) as `week 3`,
COUNT(CASE WHEN WEEK(MAX(plannedGI))+1=4 THEN 1 ELSE NULL END) as `week 4`
FROM tbl_nif,tbl_custmon,tbl_incoming
WHERE tbl_nif.so=tbl_custmon.so AND tbl_nif.bill='521513' AND tbl_incoming.shipment!=tbl_custmon.shipment
AND plannedGI!='0000-00-00'
GROUP BY tbl_custmon.so
ORDER BY tbl_custmon.so) AS grid
ORDER BY project ASC
If I not include the "count" in query, it will be show the output.
So, kindly please tell me an idea for this issue.
Big Thanks!
CONCLUSION
Put "Max" function on query makes a natural "group by".
So I put "Max" function inline with the other SELECT field.
So the query will be like this
SELECT * FROM
(SELECT project,tbl_nif.POno,tbl_custmon.so, tbl_nif.matcode, tbl_nif.prodesc, MAX(plannedGI),
COUNT(CASE WHEN WEEK(plannedGI)+1=6 THEN 1 ELSE NULL END) as `week 6`,
COUNT(CASE WHEN WEEK(plannedGI)+1=2 THEN 1 ELSE NULL END) as `week 2`,
COUNT(CASE WHEN WEEK(plannedGI)+1=3 THEN 1 ELSE NULL END) as `week 3`,
COUNT(CASE WHEN WEEK(plannedGI)+1=4 THEN 1 ELSE NULL END) as `week 4`
FROM tbl_nif,tbl_custmon,tbl_incoming
WHERE tbl_nif.so=tbl_custmon.so AND tbl_nif.bill='521513' AND tbl_incoming.shipment!=tbl_custmon.shipment
AND plannedGI!='0000-00-00'
GROUP BY tbl_custmon.so
ORDER BY tbl_custmon.so) AS grid
ORDER BY project ASC
And the output will show data that I need.
Many thanks to you :)

How to combine two count queries to their ratio?

I have two queries:
select count(*) from my_table where status="accepted"
and
select count(*) from my_table where status="rejected"
I was to find the ratio of accepted/reject so I Was wondering if it's possible to combine the two queries so I don't have to execute two queries
Putting this answer since none offered so far is correct
select count(case when status = "accepted" then 1 end) /
count(case when status = "rejected" then 1 end) as Ratio
from my_table
where status in ("accepted","rejected")
If you also need the individual counts
select count(case when status = "accepted" then 1 end) Accepted,
count(case when status = "rejected" then 1 end) Rejected,
count(case when status = "accepted" then 1 end) /
count(case when status = "rejected" then 1 end) as Ratio
from my_table
where status in ("accepted","rejected")
Note: MySQL does not have a divide by zero problem. It returns NULL when Rejected is 0.
select accepted_count, rejected_count, accepted_count/rejected_count ratio
from (
select sum(CASE WHEN status="accepted" THEN 1 ELSE 0 END) accepted_count,
sum(CASE WHEN status="rejected" THEN 1 ELSE 0 END) rejected_count
from my_table
) A
I think this will work:
SELECT (Select count(*) from my_table where status="accepted") / (select count(*) from my_table where status="rejected") AS ratio
select status, count(*) from my_table
where status in ("rejected", "accepted")
group by status;
select sum(case when status='accepted' then 1 else 0 end) as AcceptedCount,
sum(case when status='rejected' then 1 else 0 end) as RejectedCount
from my_table