SQL Syntax run operations in between records? - mysql

I have a mysql database with a table in it. This table consists of the some of the following information. It has values in one column with months Jan-May. So five months. On the adjacent column, there are "Counts" with integer values to each month. Bear in mind that there can be duplicate values of the months. So, for example, a snippet of the table could read
January | 5
January | 10
February | 1
March | 20
April | 23
April | 34
April | 43
May | 9
There are a lot more records (160). Say the average of the month is running some sql command like
select month, avg(count) from tablename group by month. However, this divides the sum of counts for each month by the number of records. A true average would divide the sum of the counts by the number of days in each month. So I have the following statements,
select month, sum(count)/31 from trendsummary.traffictype where month like 'January';
select month, sum(count)/28 from trendsummary.traffictype where month like 'February';
select month, sum(count)/31 from trendsummary.traffictype where month like 'March';
select month, sum(count)/30 from trendsummary.traffictype where month like 'April';
select month, sum(count)/31 from trendsummary.traffictype where month like 'May';
This gives me the averages for the counts for each month. So the question is...what would be the syntax if I wanted an average of the averages of Jan-April? So... I want to have statements that would take the averages (based on the number of days of the month) for each of the months, and then take the average of the averages for January, February, March, And April and spit that value out? How would one go about this? Thanks!

you can try that :
select month, sum(count)/(31+28+31+30)
from trendsummary.traffictype
where month in ( 'January' , 'February','March','April' );

Union the selects and enclose them in parentheses and treat that as you data source as in this example:
select avg(*) from (
select month, sum(count)/31 as average from ...
union select ...
union select ...
)
remember that most sql engines will require to name the computed expression column like I did (as average) at least in the first select of all union selects.

Related

MySQL query daily avg value over years for the same day

I've got a MySQL database filled with weather data, e.g. mean temperature value for every day. I would like query for the average of these values for every day the last five years.
for example:
2019-06-04 20.04
2018-06-04 18.42
2017-06-04 19.21
2016-06-04 21.22
2015-06-04 17.19
query result should be: 19.216
For now I am able to get the avg for a specific day for the last years:
select date, avg(ta) from weatherdata where date like "20%-06-04";
But I am searching for an option to get the avg value for every day in a single query if possible.
Use GROUP BY.
SELECT MONTH(date) AS month, DAY(date) AS day, AVG(ta)
FROM weatherdata
GROUP BY month, day
ORDER BY month, day

How to get specific date interval for every month in MySQL 5.7

I want to calculate some percentage etc. between 1st and 13th of every month.
Like JAN 1st to JAN 13th Do some calculation. Similarly for every month I have to make the calculation for the first 13 days. How to get the first 13 days or any number of days in MySQL?
Assuming that you have a column of date data type it could be like this:
SELECT MONTH(date_column) AS mnth,
SUM(etc) AS col1,
SUM(etc2) AS col2
FROM tbl
WHERE DAY(date_column) BETWEEN 1 AND 13
GROUP BY MONTH(date_column)

MySQL Query to group by date range?

I've got a table in MySQL that shows me number of hours logged on a daily basis. I'm trying to build a view that will allow me to quickly group my data by blocks/range of days. The simplest case would be on a monthly basis which wouldn't be difficult. I could just select the date as "%y-%m" and then group by that column.
Ex:
select time_logged, date_format(start_date, '%Y-%m') AS `month_logged`
from work_log
group by month_logged
That works fine if I am just grouping by month. But my issue is that I need to group from the 13th of the month to the 12th of the following month (ex: July 13-Aug 12, Aug 13- Sept 12, etc).
Is there an easy way to do something like that in a single query/view? I can't seem to come up with a query that works for my needs, even playing with the different date field combinations.
Subtract 13 days and do the grouping you are doing now:
select time_logged,
date_format(start_date - interval 12 day, '%Y-%m') AS `month_logged`
from work_log
group by month_logged;

Cumulative monthly reporting

I have a MySQL table of photovoltaic electricity generation data (pvdata) from which I need to produce a monthly summary table. A simplified table is shown:
id date time pvdata
1 2012-01-01 10:00 50
1 2012-01-31 12:00 60
1 2012-02-10 13:00 70
2 2012-02-08 10:00 12
2 2012-03-20 10:00 17
The monthly summary table needs to show the cumulative generation for all systems in the database, regardless of whether I have received data for that month, so for example month 3 below contains the total generation from id = 1 (data received in month 2).
Also there may be more than one data point for an id in the same month, so the report must report the max(data) for the month.
year month cum_data
2012 1 60
2012 2 82
2012 3 87
I am pretty new to this, so have struggled for a while. The best I can come up with shows the cumulative total for the month, but without including the cumulative total for ids for which there is no data in the current month:
CREATE TEMPORARY TABLE intermed_gen_report
SELECT year(date) AS year, month(date) AS month, id, max(pvdata) AS maxpvdata
FROM pvdata
GROUP BY id, year(date), month(date)
ORDER BY year(date), month(date);
SELECT year, month, SUM(maxpvdata) AS cum_data
FROM intermed_gen_report
GROUP BY year, month
ORDER BY year, month;
Giving:
year month cum_data
2012 1 60
2012 2 82
2012 3 17
I think the problem is one kind of like this http://www.richnetapps.com/using-mysql-generate-daily-sales-reports-filled-gaps/ - you will want to create a table (possibly temporary) with dates (or year / month values). However that example leaves zeros where there is no data - I think you will want to do a join on a subselect that returns the most recent data before that date (or year/ month value).
I agree I think with what Aerik suggests. You will want to join your data of what is usually called a 'date dimension table'. You can find lots of examples on how to populate said table. This is a common technique in data warehousing.
You can also do what you need in one select using sub selects. Take a look at some of the previous threads like: generate days from date range

group by month of unix timestamp field

I'm trying to get my code to output in the following format:
january 2012 - 34
february 2012 - 23
where 34 and 23 would be a count of the total rows that fall within that month that have the id_dealership of 7. I need this to output all data for every month that an assignment was ever made.
The assignments table structure is as follows:
id_dealer (int)
date_assigned (int)
I've tried this but it does not work at all:
SELECT MONTH(date_assigned), YEAR(date_assigned), COUNT(*)
FROM assignments
GROUP BY MONTH(date_assigned), YEAR(date_assigned)
SELECT
MONTH(FROM_UNIXTIME(date_assigned)),
YEAR(FROM_UNIXTIME(date_assigned)),
COUNT(*)
FROM assignments
GROUP BY
MONTH(FROM_UNIXTIME(date_assigned)),
YEAR(FROM_UNIXTIME(date_assigned))
Your date_assigned column should be of type DATE. AFAIK MONTH works on date columns
and if you want the month name from a DATE column use : MONTHNAME(date_assigned)
try this query
SELECT
MONTH(FROM_UNIXTIME(date_assigned)),
YEAR(FROM_UNIXTIME(date_assigned)),
COUNT(*)
FROM assignments
GROUP BY 1,2
For people who would like to output a DATETIME rather than a month/year combo, here's another way to solve the problem. The benefit of using DATETIME is that it can easily be plugged into data visualization libraries and tools.
SELECT
LAST_DAY(FROM_UNIXTIME(date_assigned)),
COUNT(*)
FROM assignments
GROUP BY 1
ORDER BY 1 DESC
The LAST_DAY() function returns the last day of the month for a given DATE or DATETIME value. If you'd rather grab the first day, you could select this instead: ADDDATE(LAST_DAY(SUBDATE(FROM_UNIXTIME(date_assigned), INTERVAL 1 MONTH)), 1). It adds a day to the last date then subtracts a month.
The 1 values are column position integers -- shorthand so we don't have to type LAST_DAY(FROM_UNIXTIME(date_assigned)) any more than we need to (they start at 1, not 0).
Example output:
|-------------------------------------------|------------------|
| LAST_DAY(FROM_UNIXTIME(date_assigned)) | COUNT(*) |
|-------------------------------------------|------------------|
| September 30, 2020, 12:00 AM | 34 |
|-------------------------------------------|------------------|
| August 31, 2020, 12:00 AM | 23 |
|-------------------------------------------|------------------|