Count records for each age range - mysql

I have a mysql table
TABLE name test
Id INT PRIMARY KEY
Lahir Date
Gender CHAR(1)
Nama Varchar(100)
id_desa CHAR(4)
How can I get report like this?
id_desa 0-10 11-20 21-30 31-40 41-50
10B 1 2 0 1 8
10C 2 4 7 1 0.

try
select
id_desa,
sum(case when FLOOR(DATEDIFF(Lahir,NOW())/365) between 0 and 10 then 1 else 0 end) as '0-10',
sum(case when FLOOR(DATEDIFF(Lahir,NOW())/365) between 11 and 20 then 1 else 0 end) as '11-20',
sum(case when FLOOR(DATEDIFF(Lahir,NOW())/365) between 21 and 30 then 1 else 0 end) as '21-30',
sum(case when FLOOR(DATEDIFF(Lahir,NOW())/365) between 31 and 40 then 1 else 0 end) as '31-40',
sum(case when FLOOR(DATEDIFF(Lahir,NOW())/365) between 41 and 50 then 1 else 0 end) as '41-50'
from tbl

You can try to use this query.
I assume that the table name is name_test.
SELECT id_desa,
(SELECT Count(*) FROM name_test WHERE DATE_FORMAT(FROM_DAYS(DATEDIFF(Now(),Lahir)), "%y")+0 BETWEEN 0 AND 10) as "0-10",
(SELECT Count(*) FROM name_test WHERE DATE_FORMAT(FROM_DAYS(DATEDIFF(Now(),Lahir)), "%y")+0 BETWEEN 11 AND 20) as "11-20",
(SELECT Count(*) FROM name_test WHERE DATE_FORMAT(FROM_DAYS(DATEDIFF(Now(),Lahir)), "%y")+0 BETWEEN 21 AND 30) as "21-30",
(SELECT Count(*) FROM name_test WHERE DATE_FORMAT(FROM_DAYS(DATEDIFF(Now(),Lahir)), "%y")+0 BETWEEN 31 AND 40) as "31-40",
(SELECT Count(*) FROM name_test WHERE DATE_FORMAT(FROM_DAYS(DATEDIFF(Now(),Lahir)), "%y")+0 BETWEEN 41 AND 50) as "41-50"
FROM name_test

MySQL has a very nice function called TIMESTAMPDIFF
SELECT
id_desa,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) BETWEEN 0 AND 10) `0-10`,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) BETWEEN 11 AND 20) `11-20`,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) BETWEEN 21 AND 30) `21-30`,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) BETWEEN 31 AND 40) `31-40`,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) BETWEEN 41 AND 50) `41-50`,
SUM(TIMESTAMPDIFF(YEAR, Lahir, CURRENT_DATE) > 50) `50+`
FROM tablename
GROUP BY id_desa

Related

How to Sum "case when" clause after left join without duplication

How do I get the SUM of an amount in a CASE WHEN clause?
Table real:
id
name
goal
year
10
ronaldo
5
2022
10
ronaldo
5
2022
11
messi
5
2022
11
messi
5
2022
10
ronaldo
10
2021
11
messi
10
2021
Table target:
id
name
goal
year
10
ronaldo
10
2022
11
messi
10
2022
10
ronaldo
10
2021
11
messi
10
2021
I tried inner join, but the result was wrong:
id
name
real 2022
target 2022
real 2021
target 2021
10
ronaldo
20
30
20
30
11
messi
20
30
20
30
Desired result:
id
name
real 2022
target 2022
real 2021
target 2021
10
ronaldo
10
10
10
10
11
messi
10
10
10
10
<?php
$sql = $pdo->prepare("SELECT *,
SUM( case when YEAR(real.year) = YEAR(CURDATE()) then real.goal else 0 end) AS goal_now,
SUM( case when YEAR(real.year) = YEAR(CURDATE() - INTERVAL 1 YEAR) then real.goal else 0 end) AS goal_then,
SUM( case when YEAR(target.year) = YEAR(CURDATE()) then target.goal else 0 end) AS goal_target,
SUM( case when YEAR(target.year) = YEAR(CURDATE() - INTERVAL 1 YEAR) then target.goal else 0 end) AS goal_target_then
FROM real
left join target
on id_real = id_target
group by real.id_real
having
real.id_real LIKE '1%'
");
$sql->execute();
while($data = $sql->fetch()){
?>
select
id,
name,
sum(real_goal_now) as real_goal_now,
sum(real_goal_then) as real_goal_then,
sum(target_goal_now) as target_goal_now,
sum(target_goal_then) as target_goal_then
from
(
select
a.id,
a.name,
case
when a.year = year(curdate()) then a.goal else 0 end as real_goal_now,
case
when a.year = year(curdate() - interval 1 year) then a.goal else 0 end as real_goal_then,
case
when b.year = year(curdate()) then b.goal else 0 end as target_goal_now,
case
when b.year = year(curdate() - interval 1 year) then b.goal else 0 end as target_goal_then
from
(
select
id, name, year, sum(goal) goal
from
real
group by
id, year) a,
(
select
id, name, year, sum(goal) goal
from
target
group by
id, year) b
where
a.id = b.id
and a.year = b.year
group by
a.id, a.year) c
group by
id;
<?php
$sql = $pdo->prepare("SELECT *,
SUM( case when YEAR(real.year) = YEAR(CURDATE()) then real.goal else 0 end) AS goal_now,
SUM( case when YEAR(real.year) = YEAR(CURDATE() - INTERVAL 1 YEAR) then real.goal else 0 end) AS goal_then
FROM real
left join ( select *,
SUM( case when YEAR(target.year) = YEAR(CURDATE()) then target.goal else 0 end) AS goal_target,
SUM( case when YEAR(target.year) = YEAR(CURDATE() - INTERVAL 1 YEAR) then target.goal else 0 end) AS goal_target_then
from target
group by id_target ) as t
on real.id_real = t.id_target
group by real.id_real
having
real.id_real LIKE '1%'
");
$sql->execute();
while($data = $sql->fetch()){
?>

How to replace WITH clause in SQL 4.9.5. I am using this in version 8 but my server doesnt supports that

Below is my SQL query. I am not able to run it on db version below version 8. It is perfectly running on version 8. But my live server is behind version 8. Help me in this please.
WITH ages AS
(
SELECT
ROUND(DATEDIFF(Cast(CURRENT_TIMESTAMP() as Date), Cast(dob as Date)) / 365, 0) as age
FROM artisan_bio
)
SELECT
count(case when age between 0 and 24 then 1 end) as age_00_24_cnt,
count(case when age between 25 and 34 then 1 end) as age_25_34_cnt,
count(case when age between 35 and 44 then 1 end) as age_35_44_cnt,
count(case when age between 45 and 54 then 1 end) as age_45_54_cnt,
count(case when age >= 55 then 1 end) as age_55_xx_cnt
FROM ages
This query should work:
SELECT
count(case when age between 0 and 24 then 1 end) as age_00_24_cnt,
count(case when age between 25 and 34 then 1 end) as age_25_34_cnt,
count(case when age between 35 and 44 then 1 end) as age_35_44_cnt,
count(case when age between 45 and 54 then 1 end) as age_45_54_cnt,
count(case when age >= 55 then 1 end) as age_55_xx_cnt
FROM (
SELECT
ROUND(DATEDIFF(Cast(CURRENT_TIMESTAMP() as Date), Cast(dob as Date)) / 365, 0) as age
FROM artisan_bio
) AS ages;
The change moves your first query to be a derived table with the second query.

MySQL row count with different age ranges

I have a MySQL table as follows.
emp_no emp_name dob gender
1 A 1978-10-10 Male
2 B 1985-02-20 Female
3 C 1982-04-16 Female
4 D 1980-06-27 Male
Then I need to get the following result.
age_group No of Male No of Female Total
<25 1 0 1
25-35 0 1 1
35-50 0 1 1
>50 1 0 1
I used the following query to get this output.
SELECT TIMESTAMPDIFF(YEAR, dob, NOW()) AS age_group,
COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) <25, 1, 0 ) ) AS ag_C,
COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) BETWEEN 25 AND 35 , 1, 0 ) ) AS ag_B,
COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) BETWEEN 35 AND 50 , 1, 0 ) ) AS ag_C,
COUNT( IF( TIMESTAMPDIFF(YEAR, dob, NOW()) >50, 1, 0 ) ) AS ag_D
FROM emp GROUP BY age_group
But I can not get the desired out put. Can anyone help me on this issue ?
try this
SELECT Case
when TIMESTAMPDIFF(YEAR, dob, NOW()) < 25 then '<25'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 25 and 35 then '25-35'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 36 and 50 then '36-50'
else '>50' END AS age_group,
sum(if(gender='Male', 1, 0)) as Male,
sum(if(gender='Female', 1, 0)) as Female,
COUNT(1) as total FROM emp
GROUP BY Case
when TIMESTAMPDIFF(YEAR, dob, NOW()) < 25 then '<25'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 25 and 35 then '25-35'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 36 and 50 then '36-50'
else '>50' END;
Try below:
SELECT Case
when TIMESTAMPDIFF(YEAR, dob, NOW()) < 25 then '<25'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 25 and 35 then '25-35'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 36 and 50 then '36-50'
else '>50' END AS age_group,
sum(case when gender='Male' then 1 end) as Male,
sum(case when gender='Female' then 1 end) as Female,
sum(case when gender in ('Male','Female') then 1 end) as total,
GROUP BY Case
when TIMESTAMPDIFF(YEAR, dob, NOW()) < 25 then '<25'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 25 and 35 then '25-35'
when TIMESTAMPDIFF(YEAR, dob, NOW()) between 36 and 50 then '36-50'
else '>50' END
You could try this:
select emp_no,
emp_name,
dob,
gender,
case when age < 25 then 1 else 0 end `<25`,
case when age >= 25 and age < 35 then 1 else 0 end `25-35`,
case when age >= 35 and age < 50 then 1 else 0 end `35-50`,
case when age >= 50 then 1 else 0 end `>=50`
from (
select emp_no,
emp_name,
dob,
gender,
year(now()) - year(dob) - (date_format(now(), '%m%d') < date_format(dob, '%m%d'))
age
from tbl
) a
use case when and sub-query
select
case when age_group < 25 then '<25',
case when age_group >= 25 and age_group < 35 then '25-35',
case when age_group >= 35 and age_group < 50 then '35-50',
case when age_group >= 50 then '>=50' else null end as age_grp,
sum(case when gender='Male' then 1 end) as Male,
sum(case when gender='Female' then 1 end) as Female,
sum(case when gender in ('Male','Female') then 1 else 0 end)
as total from
(
SELECT TIMESTAMPDIFF(YEAR, dob, NOW()) AS age_group,gender
FROM emp
) as t group by age_grp

Count all records including the row with no values and on two tables

what im planning to do was that it will get all records from the past month from two table(tblshoes, tblpants) and count how many orders happened as this will be used on a google chart line chart i am trying to get all data from july 30 to 1
SELECT COUNT(*) AS shoeorder, EXTRACT(DAY FROM tlDate) as pdate
FROM tblshoes
WHERE tlDate >= CURRENT_DATE - INTERVAL 1 MONTH
GROUP BY EXTRACT(DAY FROM tlDate)
Here is what my tables looks like :
tblshoes
sname tlDate
Name Here 2017-07-15
Name Again 2017-07-14
Name again and again 2017-07-13
Name im tired 2017-07-15
Name of a patient 2017-07-10
.....
tblpants
pname tlDate
Name Here 2017-07-15
Name Again 2017-07-14
Name again and again 2017-07-13
Name im tired 2017-07-15
Name of a patient 2017-07-10
Result:
shoeorder pdate
2 15
1 14
1 13
1 10
What i want:
shoeorder pdate pantorder
0 30 0
0 29 0
0 28 0
0 27 0
0 26 0
0 25 0
0 24 0
0 23 0
0 22 0
0 21 0
0 20 0
0 19 0
0 18 0
0 17 0
0 16 0
2 15 2
1 14 1
1 13 1
0 12 0
0 11 0
1 10 1
0 9 0
0 8 0
0 7 0
0 6 0
0 5 0
0 4 0
0 3 0
0 2 0
0 1 0
You need to use full outer join...
select
coalesce(a.shoeorder, 0) as shoeorder
,coalesce(a.pdate, b.pdate) as pdate
,coalesce(b.pantorder, 0) as pantorder
from (
SELECT COUNT(*) AS shoeorder, EXTRACT(DAY FROM tlDate) as pdate
FROM tblshoes
WHERE tlDate >= CURRENT_DATE - INTERVAL 1 MONTH
GROUP BY EXTRACT(DAY FROM tlDate)
) a
left join (
SELECT COUNT(*) AS pantorder, EXTRACT(DAY FROM tlDate) as pdate
FROM tblpants
WHERE tlDate >= CURRENT_DATE - INTERVAL 1 MONTH
GROUP BY EXTRACT(DAY FROM tlDate)
) b
on a.pdate = b.pdate
union
select
coalesce(a.shoeorder, 0) as shoeorder
,coalesce(a.pdate, b.pdate) as pdate
,coalesce(b.pantorder, 0) as pantorder
from (
SELECT COUNT(*) AS shoeorder, EXTRACT(DAY FROM tlDate) as pdate
FROM tblshoes
WHERE tlDate >= CURRENT_DATE - INTERVAL 1 MONTH
GROUP BY EXTRACT(DAY FROM tlDate)
) a
right join (
SELECT COUNT(*) AS pantorder, EXTRACT(DAY FROM tlDate) as pdate
FROM tblpants
WHERE tlDate >= CURRENT_DATE - INTERVAL 1 MONTH
GROUP BY EXTRACT(DAY FROM tlDate)
) b
on a.pdate = b.pdate
SELECT COUNT(*) AS shoeorder, EXTRACT(DAY FROM tlDate) as pdate
FROM (select tlDate from tblshoes
union all
select tlDate from tblpants) sub
WHERE tlDate >= CURRENT_DATE - INTERVAL 1 MONTH
GROUP BY EXTRACT(DAY FROM tlDate)
Guess you should union both tables and then apply the group by to the result query
UPDATE: Then you need a table with all dates filled (for each day). Use the table and left join the query.
SELECT COUNT(*) AS shoeorder, EXTRACT(DAY FROM adt.tlDate) as pdate
FROM all_days_table adt
LEFT JOIN (select tlDate from tblshoes
union all
select tlDate from tblpants) sub ON adt.tlDate = sub.tlDate
WHERE tlDate >= CURRENT_DATE - INTERVAL 1 MONTH
GROUP BY EXTRACT(DAY FROM adt.tlDate)

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