How to select the rows with maximum timestamp for each month? - mysql

How can I select the maximum timestamp for each month?

I think this Query will do the job.
SELECT
YEAR(START_DATE),
MONTH(START_DATE),
MAX(IFNULL(END_DATE, '9999-12-31 23:59:59'))
GROUP BY YEAR(START_DATE), MONTH(START_DATE)

This will work for you, fairly efficiently given the correct indexes.
SELECT LAST_DAY(start_date) month_ending,
MAX(end_date) max_end_date
FROM tbl
GROUP BY LAST_DAY(start_date)

Related

Avg function not returning proper value

I expect this query to give me the avg value from daily active users up to date and grouped by month (from Oct to December). But the result is 164K aprox when it should be 128K. Why avg is not working? Avg should be SUM of values / number of current month days up to today.
SELECT sq.month_year AS 'month_year', AVG(number)
FROM
(
SELECT CONCAT(MONTHNAME(date), "-", YEAR(DATE)) AS 'month_year', count(distinct id_user) AS number
FROM table1
WHERE date between '2020-10-01' and '2020-12-31 23:59:59'
GROUP BY EXTRACT(year_month FROM date)
) sq
GROUP BY 1
Ok guys thanks for your help. The problem was that on the subquery I was pulling the info by month and not by day. So I should pull the info by day there and group by month in the outer query. This finally worked:
SELECT sq.day_month, AVG(number)
FROM (SELECT date(date) AS day_month,
count(distinct id_user) AS number
FROM table_1
WHERE date >= '2020-10-01' AND
date < '2021-01-01'
GROUP BY 1
) sq
GROUP BY EXTRACT(year_month FROM day_month)
Do not use single quotes for column aliases!
SELECT sq.month_year, AVG(number)
FROM (SELECT CONCAT(MONTHNAME(date), '-', YEAR(DATE)) AS month_year,
count(distinct id_user) AS number
FROM table1
WHERE date >= '2020-10-01' AND
date < '2021-01-01'
GROUP BY month_year
) sq
GROUP BY 1;
Note the fixes to the query:
The GROUP BY uses the same columns as the SELECT. Your query should return an error (although it works in older versions of MySQL).
The date comparisons have been simplified.
No single quotes on column aliases.
Note that the outer query is not needed. I assume it is there just to illustrate the issue you are having.

Reverse order for GROUP BY in MySQL

I need to select first value for every hour from my db. But I don't know how to reverse order on GROUP BY statement.
How can i rewrite my query (now it selects last value in hour)?
SELECT HOUR(`time`) as hour, mytable.*
FROM mytable
WHERE DATE(`time`) ="2015-09-12" GROUP BY HOUR(`time`) ORDER BY `time` ASC;
This query gave me expected result:
SELECT HOUR(`time`) as hour, sortedTable.* FROM
(SELECT electrolysis.* FROM electrolysis
WHERE DATE(`time`)='2015-09-12' ORDER BY `time`) as sortedTable
GROUP BY HOUR(`time`);
You can just select the MIN HOUR in sub query , try using the query:
SELECT * from mytable WHERE `time` IN (
SELECT MIN(HOUR(`time`)) as `hour`
FROM mytable
WHERE DATE(`time`) ="2015-09-12"
GROUP BY HOUR(`time`) ) ORDER BY `time` ASC;
You can do something like this:-
SELECT sub0.min_time,
mytable.*
FROM mytable
INNER JOIN
(
SELECT MIN(`time`) AS min_time
FROM mytable
GROUP BY HOUR(`time`)
) sub0
ON mytable.`time` = sub0.min_time
WHERE DATE(`time`) ="2015-09-12"
ORDER BY `time` ASC
This is using a sub query to get the smallest time in each hour. This is then joined back against your main table on this min time to get the record that has this time.
Note that there is a potential problem here if there are multiple records that share the same time as the smallest one for an hour. There are ways around this, but that will depend on your data (eg, if you have a unique id field which is always ascending with time then you could select the min id for each hour and join based on that)
You can use below query, which is more optimized just make sure that time field should be indexed.
SELECT HOUR(m.time), m.*
FROM mytable AS m
JOIN
(
SELECT MIN(`time`) AS tm
FROM mytable
WHERE `time` >= '2015-09-12 00:00:00' AND `time` <= '2015-09-12 23:59:59'
GROUP BY HOUR(`time`)
) AS a ON m.time=a.tm
GROUP BY HOUR(m.time)
ORDER BY m.time;

Calculate average column value per day

I have the following table structure: Value (stores random integer values), Datetime` (stores purchased orders datetimes).
How would I get the average value from all Value rows across a full day?
I'm assuming the query would be something like the following
SELECT count(*) / 1
FROM mytable
WHERE DateTime = date(now(), -1 DAY)
You can GROUP BY the DATE part of DATETIME and use AVG aggregate function to find an average value for each group :
SELECT AVG(`Value`)
, DATE(`Datetime`)
FROM `mytable`
GROUP BY DATE(`Datetime`)
Looks like a simple AVG task:
SELECT `datetime`,AVG(`Value`) as AvgValue
FROM TableName
GROUP BY `datetime`
To find average of a specific day:
SELECT `datetime`,AVG(`Value`) as AvgValue
FROM TableName
WHERE `datetime`=#MyDate
GROUP BY `datetime`
Or Simply:
SELECT AVG(`Value`) as AvgValue
FROM TableName
WHERE `datetime`=#MyDate
Explanation:
AVG is an aggregate function used to find the average of a column. Read more here.
The following query will give you what u want..
SELECT DATE_FORMAT(thedate_field, '%Y-%m-%d') as theday, avg (value)
FROM mytable group by
DATE_FORMAT(thedate_field, '%Y-%m-%d')
Try It its work...
Select AVG(value),convert(nvarchar,DateTime,103) from table group by convert(nvarchar,DateTime,103)

Optimize sql query - select in select

Which is the best method for optimizing the select in select mysql query ?
This is my example:
SELECT count(distinct email)
FROM emails_stats
WHERE DATE_FORMAT(time, '%Y-%m-%d') >= '2012-12-12'
and email in (SELECT email
FROM `reminder`
WHERE DATE_FORMAT(time, '%Y-%m-%d') = '2012-12-12')
My database has over 500k entries.
SELECT count(distinct emails_stats.email)
FROM emails_stats
JOIN reminder ON emails_stats.email= reminder.email
WHERE
emails_stats.time >= CAST('2012-12-12 00:00:00' AS datetime) AND
(reminder.time BETWEEN CAST('2012-12-12 00:00:00' AS datetime) AND CAST('2012-12-12 23:59:59' AS datetime));
If you use date_format() with the table fields, mysql will need to go through each row in the table, because it needs to get the result of that date_format() function to be able to compare the value with your given string. To make it faster, create an index for the 'time' fields and use this query instead. That way mysql can determine which rows it needs just by looking up the index.
Use an exists clause instead:
SELECT count(distinct email)
FROM emails_stats
WHERE DATE_FORMAT(time, '%Y-%m-%d') >= '2012-12-12'
and exists (SELECT 1
FROM `reminder`
WHERE emails_stats.email = `reminder`.email
and DATE_FORMAT(time, '%Y-%m-%d') = '2012-12-12')
the best method is to use join here like
SELECT count(distinct emails_stats.email)
FROM emails_stats
JOIN reminder ON emails_stats.email= reminder.email
WHERE DATE_FORMAT(emails_stats.time, '%Y-%m-%d') >= '2012-12-12';

How to group by date regardless of time?

I'm trying to group by Date(). I've got 3 records with the created_at column:
2011-12-03 08:00:24, 2011-12-03 08:12:10, 2011-12-04 09:00:00
I'd like to only group by year, month and day, regardless of time. So for the example above. It should only return two rows:
2011-12-03 and 2011-12-04
How should I go about this?
... group by date(date_time_column)
This should allow you to group by year month and day
SELECT group_by_column
, DATE_FORMAT(created_at, '%Y')
, DATE_FORMAT(created_at, '%m')
, DATE_FORMAT(created_at, '%d')
FROM my_table
GROUP BY group_by_column
or if you want to do them all together.
SELECT group_by_column
, DATE_FORMAT(created_at, '%Y%m%d')
FROM my_table
GROUP BY group_by_column
Did you try the following?
SELECT
DATE(created_at) AS created_date
FROM
my_table
GROUP BY
created_date
MySQL permits GROUP BY DATE(created_at). So that would translate in ActiveRecord to .group(DATE(created_at))
In fact, that exact example is available in the Rails Guides on ActiveRecord querying.
You can use the Date() function.
http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date
mysql> SELECT DATE('2003-12-31 01:02:03');
-> '2003-12-31'
TRY
GROUP BY DATE(`date_column`)
Reference