MySQL getting percentage of count - mysql

My Data would like this
Name Similar_Percentage
A 15
B 20
C 65
I want like this
Similar_Percentage count(*)
Less than 20 2
Less than 70 1
How to write a query for this.
I know having make this but it show one by one data.

use case when
select case when Similar_Percentage<20 then 'Less than 20'
when (Similar_Percentage<70) then 'Less than 70' end as Percentage,count(*)
from table group by case when Similar_Percentage<20 then 'Less than 20'
when (Similar_Percentage<70) then 'Less than 70' end
with cte as (
select 15 as Similar_Percentage
union all
select 20
union all
select 65
)select case when Similar_Percentage<=20 then 'Less than 20'
when (Similar_Percentage<70) then 'Less than 70' end as Percentage,count(*)
from cte group by case when Similar_Percentage<=20 then 'Less than 20'
when (Similar_Percentage<70) then 'Less than 70' end
demo link
Percentage count(*)
Less than 20 2
Less than 70 1

Another approach can be like following.
SELECT 'Less than 20' Percentage,
Count(*) [Count(*)]
FROM tablename
WHERE similar_percentage <= 20
UNION ALL
SELECT 'Less than 70' Percentage,
Count(*) [Count(*)]
FROM tablename
WHERE similar_percentage <= 70
AND similar_percentage > 20

Use a case expression in a derived table (the subquery) to do the classification. GROUP BY its result:
select percentage, count(*)
from
(
select case when Similar_Percentage <= 20 then 'Less than 20'
when Similar_Percentage <= 70 then 'Less than 70'
else 'More than 70'
end as percentage
from tablename
) dt
group by percentage

MySQL allows you to use column aliases in the group by. This simplifies the query.
I also recommend an explicit order by, so you get the results in the order you want:
select (case when Similar_Percentage <= 20 then 'Less than 20'
when Similar_Percentage < 70 then 'Less than 70'
end) as Percentage,
count(*)
from cte
group by Percentage
order by min(Similar_Percentage)

Related

How to use multiple group by conditions in mysql

I have a customer_master table. In that table I have two columns called customer_id and date_of_birth.
what I want is get count of customers group by their age ranger. Something like this.
So far this is the only query I could try.
select COUNT(customer_id) AS count FROM customer_master
WHERE (DATEDIFF( CURDATE(),date_of_birth) / 365.25)<40
Please help me out with this. Thank you.
With everyone's help I found a perfect answer than you all.
SELECT CASE
WHEN (DATEDIFF( CURDATE(),STR_TO_DATE(date_of_birth, '%Y-%m-%d')) / 365) <= 20 THEN 'Below 20'
WHEN(DATEDIFF( CURDATE(),STR_TO_DATE(date_of_birth, '%Y-%m-%d')) / 365) <= 30 THEN 'Below 30'
WHEN (DATEDIFF( CURDATE(),STR_TO_DATE(date_of_birth, '%Y-%m-%d')) / 365) <= 40 THEN 'Below 40'
WHEN (DATEDIFF( CURDATE(),STR_TO_DATE(date_of_birth, '%Y-%m-%d')) / 365) <= 50 THEN 'Below 50'
ELSE 'Over 50'
END as age_group,
COUNT(customer_id)
FROM customer_master
GROUP BY age_group;
You can use the CASE operator.
SELECT CASE
WHEN (DATEDIFF( CURDATE(),date_of_birth) / 365.25) < 40 THEN 'Below 40'
ELSE 'Over 40'
END as age_group,
COUNT(customer_id)
FROM customer_master
GROUP BY age_group;
Sorry for poor formatting, it is my first answer
One solution would be to use cascading values with CASE within a subquery:
select age_group, count(customer_id) as 'count' from
(select customer_id,
year(curdate())-year(date_of_birth) as 'age',
case when (year(curdate())-year(date_of_birth)) < 20, "Below 20"
when (year(curdate())-year(date_of_birth)) < 30, "Between 20 and 29"
when (year(curdate())-year(date_of_birth)) < 40, "Between 30 and 39"
else "40 or Greater" end as 'age_group'
FROM customer_master) x
group by age_group
SELECT
(year(curdate())-year(date_of_birth)) div 20 as age_group,
COUNT(customer_id)
FROM
customer_master
GROUP BY age_group
Something like this will give you number of customers in every 20. If you want different size of group just change the number you divide by.
That is assuming you want each group to be same size e.g
1 - 20
21 - 40
41 - 60
...
If you want different sizes go with CASE solution as other have suggested.

Using case when mysql

I would like to query a total marks column using case and get the marks respective grades and store it as a separate column. I have been trying for a while now, but it keeps giving me errors.
SELECT gradecalc.StudentId,gradecalc.CourseCode, Total,
CASE TOTAL
WHEN >90 THEN 'AA'
WHEN <90 AND >85 THEN 'BA'
WHEN <85 AND >=80 THEN 'BB'
WHEN <80 AND >=75 THEN 'CB'
WHEN <75 AND >=70 THEN 'CC'
WHEN <70 AND >=65 THEN 'DC'
WHEN <65 AND >=60 THEN 'DD'
ELSE 'FF'
END AS Grade
FROM GRADECALC GROUP BY gradecalc.StudentId,gradecalc.CourseCode
The case <column> when <value> syntax can only handle equality checks. For other operators, your'd have to use a slightly different syntax:
SELECT gradecalc.StudentId,gradecalc.CourseCode, Total,
CASE
WHEN total > 90 THEN 'AA'
WHEN total < 90 AND total >= 85 THEN 'BA'
WHEN total < 85 AND total >= 80 THEN 'BB'
WHEN total < 80 AND total >=75 THEN 'CB'
WHEN total < 75 AND total >=70 THEN 'CC'
WHEN total < 70 AND total >=65 THEN 'DC'
WHEN total < 65 AND total >=60 THEN 'DD'
ELSE 'FF'
END AS Grade
FROM GRADECALC GROUP BY gradecalc.StudentId,gradecalc.CourseCode
You need to put the full expression in the case when. Your syntax of case <variable> when <constant> only works for constants.
Now, you can also simplify the expressions, because case is processed in order. So this is equivalent logic:
SELECT gc.StudentId, gc.CourseCode, gc.Total,
(CASE WHEN TOTAL > 90 THEN 'AA'
WHEN TOTAL > 85 THEN 'BA'
WHEN TOTAL >= 80 THEN 'BB'
WHEN TOTAL >= 75 THEN 'CB'
WHEN TOTAL >= 70 THEN 'CC'
WHEN TOTAL >= 65 THEN 'DC'
WHEN TOTAL >= 60 THEN 'DD'
ELSE 'FF'
END) AS Grade
FROM GRADECALC gc
GROUP BY gc.StudentId, gc.CourseCode ;
I don't think the GROUP BY is necessary, unless you have multiple rows for a given student and course. If you do, then you probably want AVG(Total) or something like that in the case statement.
With this formulation, you can readily see that "90" and "85" are suspicious. In fact, your original logic would give students with these marks an "FF", which I'm guessing is not the intention.
So:
SELECT gc.StudentId, gc.CourseCode, gc.Total,
(CASE WHEN TOTAL >= 90 THEN 'AA'
WHEN TOTAL >= 85 THEN 'BA'
WHEN TOTAL >= 80 THEN 'BB'
WHEN TOTAL >= 75 THEN 'CB'
WHEN TOTAL >= 70 THEN 'CC'
WHEN TOTAL >= 65 THEN 'DC'
WHEN TOTAL >= 60 THEN 'DD'
ELSE 'FF'
END) AS Grade
FROM GRADECALC gc;
You can try this, mate:
SELECT
gc.StudentId,
gc.CourseCode,
gc.Total,
CASE
WHEN gc.Total > 90 THEN 'AA'
WHEN gc.Total BETWEEN 85 AND 90 THEN 'BA'
WHEN gc.Total BETWEEN 80 AND 85 THEN 'BB'
WHEN gc.Total BETWEEN 75 AND 80 THEN 'CB'
WHEN gc.Total BETWEEN 70 AND 75 THEN 'CC'
WHEN gc.Total BETWEEN 65 AND 70 THEN 'DC'
WHEN gc.Total BETWEEN 60 AND 65 THEN 'DD'
ELSE 'FF'
END AS Grade
FROM
gradecalc gc
GROUP BY
gc.StudentId, gc.CourseCode;

Calculate percentage and total after create categories mysql

I've this query
SELECT
trage,
CASE trage
WHEN '<18' THEN SUM(CASE WHEN AGE <18 THEN 1 ELSE 0 END)
WHEN '18-24' THEN SUM(CASE WHEN AGE >= 18 AND AGE <= 24 THEN 1 ELSE 0 END)
WHEN '25-34' THEN SUM(CASE WHEN AGE >= 25 AND AGE <= 34 THEN 1 ELSE 0 END)
WHEN '35-44' THEN SUM(CASE WHEN AGE >= 35 AND AGE <= 44 THEN 1 ELSE 0 END)
WHEN '45-54' THEN SUM(CASE WHEN AGE >= 45 AND AGE <= 54 THEN 1 ELSE 0 END)
WHEN '>=55' THEN SUM(CASE WHEN AGE >= 55 THEN 1 ELSE 0 END)
END Total
FROM
( SELECT
t_personne.pers_date_naissance,
t_personne.pers_date_inscription,
TIMESTAMPDIFF(Year, t_personne.pers_date_naissance, t_personne.pers_date_inscription)
- CASE
WHEN MONTH(t_personne.pers_date_naissance) > MONTH(t_personne.pers_date_inscription)
OR (MONTH(t_personne.pers_date_naissance) = MONTH(t_personne.pers_date_inscription)
AND DAY(t_personne.pers_date_naissance) > DAY(t_personne.pers_date_inscription))
THEN 1 ELSE 0
END AS AGE
FROM t_personne
) AS Total
CROSS JOIN
( SELECT '<18' trage UNION ALL
SELECT '18-24' UNION ALL
SELECT '25-34' UNION ALL
SELECT '35-44' UNION ALL
SELECT '45-54' UNION ALL
SELECT '>=55'
)a
GROUP BY trage
ORDER BY FIELD(trage, '<18', '18-24', '25-34', '35-44', '45-54', '>=55')
it give a table with two columns trage and Total for all categories
How to add a column percentage with a line TOTAL for the column Total and %
Thanks for your help
For the time being, you can't do this. To support this MySQL needs Window Function support which it still doesn't have. If you need functions like these I would recommend switching to PostgreSQL.
Also take a look at this question: MySql using correct syntax for the over clause

mysql USE CASE STATEMENT as variable

I have the following query with a quite large:
SELECT
DATE(added_on) 'Week Of',
COUNT(*) 'No. Updates',
(CASE WHEN COUNT(*) <= 500 THEN 6.75 WHEN COUNT(*) <= 750
THEN 6.30 WHEN COUNT(*) <= 1000 THEN 6.00 WHEN COUNT(*) <= 1250
THEN 5.50 ELSE 4.60 END
) Rate
Rate * COUNT(*) // HOW TO DO THIS??
FROM
Fox_title
GROUP BY
WEEK(added_on)
ORDER BY
added_on
How would I multiple the COUNT(*) * the Rate that I have from my CASE statement? Or do I have to write that CASE statement again?
Either repeat the case or use a subquery:
select t.*, t.Rate * `No. Updates`
from (SELECT DATE(min(added_on)) as `Week Of`, COUNT(*) as `No. Updates`,
(CASE WHEN COUNT(*) <= 500 THEN 6.75
WHEN COUNT(*) <= 750 THEN 6.30
WHEN COUNT(*) <= 1000 THEN 6.00
WHEN COUNT(*) <= 1250 THEN 5.50
ELSE 4.60
END) as Rate
FROM Fox_title
GROUP BY WEEK(added_on)
) t
ORDER BY `Week Of`;
I made a few other changes to your query. First, I changed the single quotes around the column aliases to back ticks. Single quotes should be used, in general, only for string constants. Back ticks are the MySQL method for enclosing identifiers.
I also changed date(addon) to date(min(addon)). This ensures that you will get the earliest date in the week. Otherwise, you get an arbitrary date.

Grouping items between 2 numbers

I have a query that looks like this:
select
price,
item_id,
sum(price),
count(item_id)
from transactions
group by
(price <= 20),
(price between 21 and 30),
(price between 31 and 40),
(price between 41 and 50),
(price > 50)
I have never done a group like this before when I wrote it I was just guessing to see if the query was even valid, and it was. But my question is, is it really getting me what I want?
I want all transactions grouped by:
Items that cost less than or equal to $20
Items that cost between $21 and $30
Items that cost between $31 and $40
Items that cost between $41 and $50
Items that cost more than $50
So, is that query doing what I am asking?
The way to do this in standard SQL (and MySQL) is to use the case statement. Also, I put the definition in a subquery like this:
select pricegrp, sum(price), count(item_id)
from (select t.*,
(case when price <= 20 then '00-20'
when price between 21 and 30 then '21-30'
when price between 31 and 40 then '31-40'
when price between 41 and 50 then '41-50'
when price > 50 then '50+'
end) as pricegrp
from transactions t
) t
group by pricegrp
Also, do you want to group by item_id as well? Or are you just trying to return one arbitrary item? Based on what you want, I'm removing the item_id from the select clause. It doesn't seem necessary.
Your query actually does work in MySQL, in the sense that it runs. It is going to produce one row for each group that you want, so in that sense it "works". However, within each group, it is going to choose an arbitrary price and item_id. These are not explicitly mentioned in the group by clause, so you are using a MySQL (mis)feature called Hidden Columns. Different runs of the query or slight changes to the data or slight changes to the query can change the values of price and item_id returned for each group.
I strongly suggest that you actually name the group. This makes the query and the output much clearer.
Also, I recommend that you get in the habit of putting all columns in the select in the group by clause. There are a few cases where hidden columns are actually useful, but I think, in general, you should depend on them sparingly.
If the price is not stored as an integer, then correct logic is:
select pricegrp, sum(price), count(item_id)
from (select t.*,
(case when price <= 20 then '00-20'
when price <= 30 then '21-30'
when price <= 40 then '31-40'
when price <= 50 then '41-50'
when price > 50 then '50+'
end) as pricegrp
from transactions t
) t
group by pricegrp
SELECT
price,
item_id,
sum(price),
count(item_id),
IF(price<=20,0,IF(price<=30,1,IF(price<=40,2,IF(price<=50,3,4)))) AS pricegroup
FROM transactions
GROUP BY pricegroup
or even
SELECT
price,
item_id,
sum(price),
count(item_id)
FROM transactions
GROUP BY
IF(price<=20,0,IF(price<=30,1,IF(price<=40,2,IF(price<=50,3,4))))
SELECT price,
item_id,
SUM(CASE WHEN price <= 20 THEN price ELSE 0 END) `(price <= 20) SUM`,
SUM(CASE WHEN price <= 20 THEN 1 ELSE 0 END) `(price <= 20) COUNT`,
SUM(CASE WHEN price between 21 and 30 THEN price ELSE 0 END) `(price <= 20) SUM`,
SUM(CASE WHEN price between 21 and 30 THEN 1 ELSE 0 END) `(price <= 20) COUNT`,
SUM(CASE WHEN price between 31 and 40 THEN price ELSE 0 END) `price between 31 and 40 SUM`,
SUM(CASE WHEN price between 31 and 40 THEN 1 ELSE 0 END) `price between 31 and 40 COUNT`,
SUM(CASE WHEN price between 41 and 50 THEN price ELSE 0 END) `price between 41 and 50 SUM`,
SUM(CASE WHEN price between 41 and 50 THEN 1 ELSE 0 END) `price between 41 and 50 COUNT`,
SUM(CASE WHEN price > 50 THEN price ELSE 0 END) `price > 50 SUM`,
SUM(CASE WHEN price > 50 THEN 1 ELSE 0 END) `price > 50 COUNT`
FROM transactions
GROUP BY price, item_id