Calculating Value Count and Percentage - mysql

I have a table
Currently Enrolled
The table is basically to get an idea of how many supporters, undecided, and opposition they were. Then once I get the count I wanted to then do another calculation to find out what that percentage was.
Essentially what I want to be able to do is:
Count the total number of supporters:
SELECT count(*) AS 'SUPPORTERS' FROM CURRENTLY ENROLLED WHERE
status = 'Supporter'
results were 13
Count the total number of opposition:
SELECT count(*) AS 'OPPOSITION' FROM CURRENTLY ENROLLED WHERE value = 'Opposition'
results were 11
Count the total number of undecided persons using a similar statement:
SELECT count(*) AS 'UNDECIDED' FROM CURRENTLY ENROLLED WHERE value = 'Undecided'
results were 5
So with the count, I can see that they're 29 total individuals. I wanted to be able to get the percentage of each of them separately. Something like
13/29 * 100 = 44%
11/29 * 100 = 37%
5/29 * 100 = 17%
However, I am lost on how to write this query.
Hope I am making this clear as to the intentions.

Use a CTE for the total and group by status for the percentage:
with cte as (select count(*) as cnt from `currently enrolled`)
select status, sum(100)/cnt
from `currently enrolled`, cte
group by 1

Related

SQL - How To Add Rows Between a Range of Numbers and Make Their Value 0

SQL Query I Am Working With
Result from the table
What I am trying to accomplish is that instead of just having values for places where num_opens is actually counted, I would want to have it show all potential num_opens values between the minimum and maximum value, and their total to be 0. For example, in the photo we see a jump between
num_opens: 7 Total: 1
num_opens: 10 Total: 1
But I would like it to be
num_opens: 7 Total: 1
num_opens: 8 Total: 0
num_opens: 9 Total: 0
num_opens: 10 Total: 1
and similarly for all potential num_opens values between the minimum and maximum (11 - 15, 15 - 31, 31 - 48). It is tricky because everyday the maximum value could be different (today the max is 48, but tomorrow it could be 37), so I would need to pull the max value somehow.
Thank you!
You can use generate_array() and unnest():
select num_opens, count(t.num_opens)
from (select min(num_opens) as min_no, max(num_opens) as max_no
from t
) x cross join
unnest(generate_array(t.min_no, t.max_no)) num_opens left join
t
on t.num_opens = num_opens
group by num_opens;
You need a reference table to start with. From your picture you have something called users, but really any (big enough) table will do.
So to start, you'll build the reference table using a rank() or row_count() function. Or if your users.id has no gaps it's even easier to use that.
SELECT *, rank() OVER (ORDER BY id) as reference_value FROM users
This will generate a table 1....n for users.
Now you join onto that, but count from the joined in table:
SELECT
a.reference_value, count(b.num_opens) as total
FROM
(SELECT rank() OVER (ORDER BY id) as reference_value from users) a
LEFT JOIN
[whatever table] b ON a.reference_value = b.num_opens
GROUP BY
a.reference_value
But this is too many rows! You definitely have more users than these event counts. So throw a quick filter in there.
SELECT
a.reference_value, count(b.num_opens) as total
FROM
(SELECT rank() OVER (ORDER BY id) as reference_value from users) a
LEFT JOIN
[whatever table] b ON a.reference_value = b.num_opens
WHERE
a.reference_value <= (SELECT max(num_opens) FROM [whatever table])
GROUP BY
a.reference_value

Unique MySQL query

I really am struggling with a MySQL query, I have a table named 'info' and in it I have a column called 'rating' in it I have ratings between 1-10.
Now I need to generate a percentage value of how many ratings are from 1-6 and 7-8 and 9-10 but I need them to display desperately and after that I need a second query that can subtract the percentage value of the results from 1-6 and 9-10.
The query below is as close as I could get from all my research however I don't know how to get a percentage of ratings 1-6 only and not all of them and also how to get a second query to subtract the 1-6 and 9-10 rating percentages. Any help would be amazing.
SELECT rating,
COUNT(*) AS Count,
(COUNT(*) / _total ) * 100 AS Percentege
FROM info,
(SELECT COUNT(*) AS _total FROM info) AS myTotal
GROUP BY rating
Try this:
select if(rating between 1 and 6, '1-6',
if( rating between 7 and 8, '7-8',
'9-10' )
) as rating_range,
count(1) as num
from info
group by rating_range
fiddle code

Mysql calculate with the max() value

I'm a bit stuck cause am not sure if I am looking the wrong way casue I can't find anything related to what I am looking for. So I want to give an example for what I am trying to do. NOTE: not real scenario.
I have a count on a field:
SELECT count(user_id)
FROM usersgroups
group by user_id
Now I want to make a calc with the max value from the count. Something like:
SELECT count(user_id) as count,
SUM(max(count(user_id)) / count(user_id)) as blub
FROM usergroups
group by user_id
But I get error invalid use of group function cause I think I cant use the COUNT() function inside the SUM function?
So is there any other way to make that calculation.
P.S. the calc is for calculating the percentage of the max value to the record/current value.
UPDATE
So what I expect is a percentage like
count | percentage
5 | 1
4 | 0.8
3 | 0.6
2 | 0.3
1 | 0.2
5/5 = 1
4/5 = 0.8
3/5 = 0.6
2/5 = 0.4
1/5 = 0.2
In a separate Derived Table, you can fetch the maximum count value out of all the counts. I have simply used ORDER BY COUNT(user_id) DESC LIMIT 1 to fetch the same.
CROSS JOIN this result-set with the usergroups table, so that every row in the usergroups table has access to the maximum count value.
Now, you can simply use the GROUP BY and appropriate aggregation to determine the "percent".
Note that, for GROUP BY to be valid, SELECT clause must contain either aggregated columns/expressions only, or the columns specified in the GROUP BY clause. That is why MAX() is used over the maximum count value. Since that value is only a scalar, so MAX() will return the same value only.
Try the following:
SELECT
ug.user_id,
COUNT(ug.user_id) AS user_count,
COUNT(ug.user_id) / MAX(mcnt.count) AS percent
FROM
usergroups AS ug
CROSS JOIN
(
SELECT COUNT(user_id) AS count
FROM usersgroups
GROUP BY user_id
ORDER BY COUNT(user_id) DESC LIMIT 1
) AS mcnt
GROUP BY ug.user_id
ORDER BY user_count DESC
Count available user_id as subquery, then divide user_id values by the sum of count.
select user_id/ sum(count) as percentage
from(
select count(user_id) as count , user_id
from usergroups
where user_id != 0
group by user_id
) as A
group by count, user_id

Giving a result with a sub query and a formula?

I have this issue that is going around my head lately, I wanna know how many of my users can have more than a 50% of profit in their accounts. So, as you can see in the table, I have investment and earnings, so logically I must do a percentage for having the profit. Like: ((earnings - investment * 100) / investment)
ID Investment (euros) Earnings (euros)
13 2 3.4
14 1 0
15 4 7
16 12 20.76
From here everything is ok, but my question is, how can I calculate and show at the same time the users that have more than a 50% of profit?
I made this simple query that works but don't shows the users that have more than 50%, shows everyone.
select id, ((MAX(earnings)-investment)*100)/investment
from users
group by id, investment
;
So, my idea was to create a subquery, but I have a great issue with this:
select id
from users
where 50 < (
select (((MAX(earnings)-investment)*100)/investment)
from users
group by investment
)
group by id
;
I received this error:
Detail: Expected no more than one row to be returned by expression
I don't know what I'm doing wrong. Jalp!
Isn't this the formula?
select id, (sum(earnings) - sum(investment))*100 / sum(investment) as profit
from users
group by id;
Then if you want to filter, add:
having profit > 50
To get the count, use a subquery:
select count(*)
from (select id, (sum(earnings) - sum(investment))*100 / sum(investment) as profit
from users
group by id
) u
where profit > 50;

Error in subquery

im stuck here and i don't know how to fix it.
I have a db table which has users ID, user grade and date when someone has voted for that user (3 fields).
Im trying to read the user that has the highest average grade for todays date, limited to one.
But the problem is that i want to read only users that have 5 or more votes.
My query looks like this, but im getting an error:
SELECT
idusers,
AVG(votes) AS Grade
FROM rank
WHERE (data = '{$dbDate}')
AND ((SELECT count(ID) + 1 FROM rank) AS tmpcount WHERE tmpcount>4)
GROUP BY idusers
ORDER BY Grade DESC
LIMIT 1
Without the tmpcount>4 clause this query is working ok, but I need to count the Id's.
You have to use HAVING to filter the result set on aggregated values such as COUNT (SUM, MIN, MAX, AVG, …):
SELECT idusers, AVG(votes) AS Grade
FROM rank
WHERE (data = '{$dbDate}')
GROUP BY idusers
HAVING COUNT(*) > 4
ORDER BY Grade DESC
LIMIT 1