I need the way to aggregate based on column value using MySQL - mysql

I am learning Charts in Laravel, i need to draw Line graph for daily Student Attendance for those students come late or on time. I tried to write MYSQL query but it doesn't work
I tried subquery on same table to get data for daily students and i also need 7 dates only not full date, like date is stored in db as 09/08/2019 but i need it as 08 as date.
SELECT Date, COUNT(*) AS TimeStudent
FROM attendance WHERE `Attendance`='OnTime' AND (SELECT COUNT(*) AS
LateStudent FROM attendance
WHERE `Attendance`='Late'
GROUP BY `Date`
ORDER BY LateStudent DESC)
GROUP BY `Date`
ORDER BY TimeStudent DESC
but i got
[Err] 1241 - Operand should contain 1 column(s)
, because i can't use to fetch Date again in subquery while use it after where clause. Any one help me plz.

Here is a way to aggregate based on column value.
This query will give you count of on time and late student for a particular date.
SELECT
`Date`,
DATE_FORMAT(`Date`, '%d') AS Month_Date, -- You can modify it as per your requirement
SUM(IF(`Attendance` = 'OnTime', 1, 0)) AS OnTime_Count,
SUM(IF(`Attendance` = 'Late', 1, 0)) AS Late_Count
FROM attendance
WHERE `Date` >= CURRENT_DATE - INTERVAL 7 DAY
GROUP BY `Date`;

Related

Count sum of different rows and save in a single row BigQuery

I am doing the data cleaning in a BigQuery. I managed to count each of the variables. However there are some redundant info with different variables, so I need to merge the number and save the overall total in a single row.
This is my work:
SELECT
day,
COUNT(*) as Total,
FROM
table
where day<> 'null'
GROUP BY day
-- HAVING COUNT(*) >= 10?
ORDER BY COUNT(*) DESC;
The result is
What should I add so the Monday and Mndy is added in a single row? Thanks
SELECT
CASE WHEN day in ('Monday', 'Mndy') THEN 'Monday' ELSE day END day,
COUNT(*) as Total,
FROM
table
where day<> 'null'
GROUP BY 1
-- HAVING COUNT(*) >= 10?
ORDER BY COUNT(*) DESC;

related to query using SQL

In oracle sql, how to get the count of newly added customers only for the month of april and may and make sure they werent there in the previous months
SELECT CUSTOMER ID , COUNT(*)
FROM TABLE
WHERE DATE BETWEEN '1-APR-2018' AND '31-MAY-2018' AND ...
If we give max (date) and min(date), we can compare the greater date to check if this customer is new , correct?
expected output is month count
april ---
may ---
should show the exact count how many new customers joined in these two months
One approach is to use aggregation:
select customer_id, min(date) as min_date
from t
group by customer_id
having min(date) >= date '2018-04-01 and
min(date) < date '2018-06-01';
This gets the list of customers (which your query seems to be doing). To get the count, just use count(*) and make this a subquery.

Calculating percent of each row value in MySQL in a certain date range

I want to get the first 4 rows with the highest value in a certain date range of a table in a mysql database. So I can do it with this code line, for example:
SELECT MONTH(date) as month, amount from sales where date >='2014-01-01' AND date <='2014-12-31' ORDER BY amount DESC LIMIT 4
But I want to add a new column with the percentage of each value, I tried with this line:
SELECT MONTH(date) as month, amount, round(amount*100/sum(amount) ,1) as 'percent' from sales where date >='2014-01-01' AND date <='2014-12-31' ORDER BY `amount` DESC LIMIT 4
But it doesn't work. How can I get it? I'd like some help.
Here's one way of doing it. Providing snippets of raw data also helps. Creating an sql fiddle helps even more!!
select month, amount, round(amount*100/total,1) as percent
from
(
select MONTH(date) as month, amount
from sales
where date >='2014-01-01' AND date <='2014-12-31'
ORDER BY amount DESC LIMIT 4
) c JOIN (
select sum(amount) as total
from sales
where date >='2014-01-01' AND date <='2014-12-31'
) t

Moving average in SQL

I have a MySQL database populated with power consumption over 20 years.
I want to query the average of the power consumption over every month, from a given month.
For example with this database,
date power_consumption
2014/03/30 30
2014/04/30 40
2014/05/30 50
2014/06/30 20
The result would be, from 2014/04
month average_so_far_from_april_2014
2014/04 40.0
2014/05 45.0
2014/06 36.667
If I cannot achieve this in one query, what query should I go for to retrieve the most useful data for this task? (My naive approach is to query the whole table out and calculate the average in my application.)
Join the table of sub query against the consumption table which gets the unique months against the table of consumption, with a join condition that the year / month is less than or equal to the one from the sub query and use the AVG aggregate function on the power consumption from the table grouped by the year / month
Something like this:-
SELECT consumption_month,
AVG(b.power_consumption)
FROM
(
SELECT DISTINCT DATE_FORMAT(`date`, '%Y%m') AS consumption_month FROM consumption_table a
) a
INNER JOIN consumption_table b
ON consumption_month >= DATE_FORMAT(b.`date`, '%Y%m')
WHERE b.`date` >= '2014/04/01'
GROUP BY consumption_month
SQL fiddle:-
http://www.sqlfiddle.com/#!2/16588/2
If you only had one record per month you could simplify it more by just doing a join of the table against itself without the need for the sub query.
GROUP BY is for this kind of problems. The average is calculated for each distinct value of the expression the the GROUP BY clause.
SELECT DATE_FORMAT(date, '%Y/%m'), AVG(power_consumption)
FROM table_name
WHERE date > ...
GROUP BY DATE_FORMAT(date, '%y/%m')
ORDER BY DATE_FORMAT(date, '%y/%m')
You get the average for each month, DATE_FORMAT(date, '%y/%m') is year and month in format YYYY/MM

MySQL query predominant non-numeric value

I'm looking for a function to return the most predominant non numeric value from a table.
My database table records readings from a weatherstation. Many of these are numeric, but wind direction is recorded as one of 16 text values - N,NNE,NE,ENE,E... etc in a varchar field. Records are added every 15 minutes so 95 rows represent a day's weather.
I'm trying to compute the predominant wind direction for the day. Manually you would add together the number of Ns, NNEs, NEs etc and see which there are most of.
Has MySQL got a neat way of doing this?
Thanks
It's difficult to answer your question without seeing your schema, but this should help you.
Assuming the wind directions are stored in the same column as the numeric values you want to ignore, you can use REGEXP to ignore the numeric values, like this:
select generic_string, count(*)
from your_table
where day = '2014-01-01'
and generic_string not regexp '^[0-9]*$'
group by generic_string
order by count(*) desc
limit 1
If wind direction is the only thing stored in the column then it's a little simpler:
select wind_direction, count(*)
from your_table
where day = '2014-01-01'
group by wind_direction
order by count(*) desc
limit 1
You can do this for multiple days using sub-queries. For example (assuming you don't have any data in the future) this query will give you the most common wind direction for each day in the current month:
select this_month.day,
(
select winddir
from weatherdatanum
where thedate >= this_month.day
and thedate < this_month.day + interval 1 day
group by winddir
order by count(*) desc
limit 1
) as daily_leader
from
(
select distinct date(thedate) as day
from weatherdatanum
where thedate >= concat(left(current_date(),7),'-01') - interval 1 month
) this_month
The following query should return you a list of wind directions along with counts sorted by most occurrences:
SELECT wind_dir, COUNT(wind_dir) AS count FROM `mytable` GROUP BY wind_dir ORDER DESC
Hope that helps