count user from different districts by selected age - mysql

I am trying to write mysql query that would get me the data about the count of users in my different districts by some selcted age .
for example : if i choose age 0-14 i want to get how many users from 'north' ,'south' and etc are between age 0 and 14.
i'm writing the current query :
SELECT sum(case when districts.`districtId` = 1 then 1 else 0 end) as 'North',
sum(case when districts.`districtId` = 4 then 1 else 0 end) as 'Center',
sum(case when districts.`districtId` = 6 then 1 else 0 end) as 'South', , (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(userDetails.birthDate2, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(userDetails.birthDate2, '00-%m-%d'))) as age
from .... where age between 0 and 14
but i get the error : unknown age column.
is there other way to write this query ?!

Try
SELECT districts.districtId, count(userDetails.*)
FROM userDetails, districts
INNER JOIN districts ON userDetails.districtId = districts.districtId
WHERE userDetails.birthDate2 >= (DATE_SUB(NOW(), INTERVAL 14 YEAR)
AND userDetails.birthDate2 <= (DATE_SUB(NOW(), INTERVAL 0 YEAR)
GROUP BY districts.districtId
And for your other question, try to post the database schema..
EDIT :
I Forgotten the GROUP BY Clausse

Since you don't give the full query, try this, filling in with your values :
Select districts.districtId, count(*) as DistrictwiseCount From ... Where age_criterion_goes_here
Group By districts.districtId

Related

How to create a loop on mysql query and display all results at once

I'm currently trying to get the customers' retention rates using the following query:
set #DAY1 = 0;
set #DAY30 = 0;
set #DAY90 = 0;
SET #order_month = 1;
SET #order_year = 2020;
SELECT
#DAY1/COUNT(uid) AS D1,
#DAY30/COUNT(uid) AS D30,
#DAY90/COUNT(uid) AS D90
FROM
(
SELECT
uid,
case when DATEDIFF(date(lastConnection), date(accountCreation)) >= 1 then #DAY1:=#DAY1+1 END AS DAY1,
case when DATEDIFF(date(lastConnection), date(accountCreation)) >= 30 then #DAY30:=#DAY30+1 END AS DAY30,
case when DATEDIFF(date(lastConnection), date(accountCreation)) >= 90 then #DAY90:=#DAY90+1 END AS DAY90
from user
where month(accountCreation) = #order_month
and year(accountCreation) = #order_year
)
AS T1
This works as expected but what I would like to add is some sort of loop that would increment the #order_month variable by one (as well as the #order_year variable when we reach a new year). The increment would go as far as August 2022. I would like the result of each 'Select' to be displayed at once. Is that possible and if yes, how could I do that?
If I get your intention right, you just want to calculate the percentage of users whose account was created at least 1 day (30 days, 90 days) before their last login. And you want to calculate this for each year and month based on accountCreation, that is something like
SELECT year(accountCreation) year,
month(accountCreation) month,
sum(CASE WHEN DATEDIFF(date(lastConnection), date(accountCreation)) >= 1 THEN 1 END) / count(*) AS D1,
sum(CASE WHEN DATEDIFF(date(lastConnection), date(accountCreation)) >= 30 THEN 1 END) / count(*) AS D30,
sum(CASE WHEN DATEDIFF(date(lastConnection), date(accountCreation)) >= 90 THEN 1 END) / count(*) AS D90
FROM user
GROUP BY year, month;
In other words: there's no need for a loop.

Unrecognized statement type. (near with)

I have query like below for get sum of purchase and sold traffic.
SELECT DATE_FORMAT(order_time,'%d')AS date,
SUM(CASE WHEN seller_id = 1 THEN visitor_quantity ELSE 0 END) AS totalSold,
SUM(CASE WHEN buyer_id = 1 THEN visitor_quantity ELSE 0 END) AS totalBought
FROM `tbl_orders`
WHERE buyer_id = 1 OR seller_id = 1
GROUP BY DATE(order_time)
Its working fine and giving me result like below
Since I am looking for get all dates between provided date range with 0 if there no any record for that date.
So I am trying following query
with recursive all_dates(dt) as (
-- anchor
select '2021-12-01' dt
union all
-- recursion with stop condition
select dt + interval 1 day from all_dates where dt + interval 1 day <= '2021-12-31'
)SELECT DATE_FORMAT(order_time,'%d')AS date,SUM(CASE
WHEN seller_id = 1
THEN visitor_quantity
ELSE 0
END) AS totalSold, SUM(CASE
WHEN buyer_id = 1
THEN visitor_quantity
ELSE 0
END) AS totalBought FROM `tbl_orders` WHERE buyer_id = 1 OR seller_id = 1 GROUP BY DATE(order_time)
I have found query tutorial here.
But its giving me error called Unrecognized statement type. (near with) in phpmyadmin and giving same result as above image.
my phpmyadmin and marialdb version information is like this.
Let me know if anyone here can help me for same
Thanks!
This is a PhpMyAdmin bug. You need to upgrade to 5.5.0 to get the fix.

SELECT records using multiple critira

I have a table named all_data with fields date, value, and other fields.
I need to select last 7, 14, and 30 days from the database. There can be several entries with the same date like
date value
10-25-16 30
10-25-16 24
10-26-16 42
Here is the SELECT Statment I have that works for less than 30 days
$sql = "SELECT type_entry, COUNT(value) as val_count, FLOOR(SUM(value)) as sum_glu FROM all_data
WHERE DATEDIFF(NOW(), date) < 30 AND type_entry = 'Glucose'
ORDER BY date";
I want the same query 2 more times but changing the DATEDIFF statement with <14 and <7 so I end up with val_count1, val_count2, val_count3, sum_glu1, sum_glu2, sumglu3 I will use those to calculate the average of each.
I do not know enough SQL to figure out how to do it.
Here is a sample of readings
10/17/2016 116
10/17/2016 277
10/17/2016 145
10/18/2016 150
10/18/2016 125
10/19/2016 200
I need the number of records from 10/19/2016 for 7 days then I can do a weekly average of the readings.
You can use conditional aggregation here:
SELECT type_entry,
SUM(CASE WHEN DATEDIFF(NOW(), date) < 30 THEN 1 ELSE 0 END) AS val_count_30,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 30 THEN value ELSE 0 END)) AS sum_glu_30,
SUM(CASE WHEN DATEDIFF(NOW(), date) < 14 THEN 1 ELSE 0 END) AS val_count_14,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 14 THEN value ELSE 0 END)) AS sum_glu_14,
SUM(CASE WHEN DATEDIFF(NOW(), date) < 7 THEN 1 ELSE 0 END) AS val_count_7,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 7 THEN value ELSE 0 END)) AS sum_glu_7
FROM all_data
WHERE type_entry = 'Glucose'
ORDER BY date
If you just want the average of value for a 7 day period starting on 10/19/2016 for 7 days then you can just use a WHERE clause:
SELECT type_entry,
AVG(value) AS avgValue
FROM all_data
WHERE date BETWEEN '2016-10-19' AND DATE_ADD('2016-10-19', INTERVAL 7 DAY) AND
type_entry = 'Glucose'
GROUP BY type_entry
Basically you can retrieve all rows with criteria < 30 and all your following criterias contain within this one. You could add a CASE expression within aggregate functions to only perform aggregation within rows that match your criteria. All I did was changed the < X for every pair of columns:
SELECT
type_entry,
COUNT(CASE WHEN DATEDIFF(NOW(), date) < 30 THEN value END) as val_count1,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 30 THEN value END)) as sum_glu1,
COUNT(CASE WHEN DATEDIFF(NOW(), date) < 14 THEN value END) as val_count2,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 14 THEN value END)) as sum_glu2,
COUNT(CASE WHEN DATEDIFF(NOW(), date) < 7 THEN value END) as val_count3,
FLOOR(SUM(CASE WHEN DATEDIFF(NOW(), date) < 7 THEN value END)) as sum_glu3
FROM all_data
WHERE DATEDIFF(NOW(), date) < 30 AND type_entry = 'Glucose'
GROUP BY type_entry
ORDER BY date
Also, note that I added the missing GROUP BY clause. Even though MySQL allows it, many different databases would yield an error. The recommended way is not to rely on MySQL mechanism in this matter.

MySQL results by date

Maybe there is a simple fix but I can't seam to figure it out. I'll try my best to explain my situation.
I'm working on a MySQL query that will return results within date range (in column A), and for date range - 1 year (in column B). I need to group results by month day and not by year. So I would like to have something like this:
2014 2013
----------------
01-01 6 8
01-03 7 0
01-04 4 1
01-08 0 13
01-21 11 7
In my current query (below) I get results like this (because of ELSE in CASE):
2014 2013
----------------
01-01 0 8
01-03 7 0
01-04 0 1
01-08 0 13
01-21 0 7
QUERY:
SELECT
DATE_FORMAT(table.date, '%e.%c.') AS date,
(CASE WHEN DATE(table.date) BETWEEN '2014-01-01' AND '2014-02-01' THEN ROUND(SUM(table.field), 2) ELSE 0 END) AS field_2014,
(CASE WHEN DATE(table.date) BETWEEN '2013-01-01' AND '2013-02-01' THEN ROUND(SUM(table.field), 2) ELSE 0 END) AS field_2013
FROM table
WHERE
(DATE(table.date) BETWEEN '2014-05-01' AND '2014-06-01' OR DATE(table.date) BETWEEN '2013-05-01' AND '2013-06-01')
GROUP BY
DATE_FORMAT(table.date, '%c.%e.')
What should I put in ELSE and how can I achieve this functionality?
Thank you for your time
You need aggregation functions. I would recommend:
SELECT DATE_FORMAT(t.date, '%e.%c.') AS date,
SUM(CASE WHEN year(t.date) = 2014 THEN ROUND(SUM(t.field), 2) ELSE 0 END) AS field_2014,
SUM(CASE WHEN year(t.date) = 2013 THEN ROUND(SUM(t.field), 2) ELSE 0 END) AS field_2013
FROM table t
WHERE year(t.date) in (2013, 2014) and month(t.date) = 5
GROUP BY DATE_FORMAT(t.date, '%c.%e.');
I would also recommend using the format '%m-%d'. Having the month then the year means that order by will work on the column. Having all the dates be the same width ("05/01" rather than "5/1") better corresponds to your desired output.

Row count where column1='value1' and column1='value2' group by column2

I have a table like this:
date day weather
2000-01-01 Monday Sunny
2000-01-02 Tuesday Rainy
. . .
I want to get number of rainy Mondays and sunny Mondays in one query like
day rainy_d sunny_d
Monday 2 5
How to accomplish that in Mysql and PostgreSQL?
select `Day`,
SUM(case when weather = 'Sunny' THEN 1 ELSE 0 end) as Sunny_D,
SUM(case when weather = 'Rainy' THEN 1 ELSE 0 end) as Rainy_D
FROM YOURTABLENAME
Where day = 'Monday'
Group by `Day`
Standard SQL, works in both:
SELECT
day,
SUM(CASE WHEN weather = 'Rainy' THEN 1 ELSE 0 END) AS rainy_d,
SUM(CASE WHEN weather = 'Sunny' THEN 1 ELSE 0 END) AS sunny_d
FROM yourtable
GROUP BY day
More concise version - MySQL only:
SELECT
day,
SUM(weather = 'Rainy') AS rainy_d,
SUM(weather = 'Sunny') AS sunny_d
FROM yourtable
GROUP BY day
More concise version - PostgreSQL only:
SELECT
day,
SUM((weather = 'Rainy')::int) AS rainy_d,
SUM((weather = 'Sunny')::int) AS sunny_d
FROM yourtable
GROUP BY day
The column day is probably redundant. I would delete it without substitution. The column date holds all the information. Then your query could look like this ..
In PostgreSQL:
SELECT to_char(date, 'Day') AS day
,COUNT(NULLIF(weather,'Sunny')) AS rainy_d
,COUNT(NULLIF(weather,'Rainy')) AS sunny_d
FROM tbl
GROUP BY 1;
In MySQL:
SELECT DAYNAME(date) AS day
... rest identical
The NULLIF() construct works for exactly two distinct (non-null) values in the column weather and is standard SQL. For more values use the alternatives provided by #Mark and #xQbert.