简体   繁体   中英

MySQL select dates between with date functions and min max

Why does this return '2015-01-19'?:

SELECT date
FROM hours 
HAVING date BETWEEN DATE_SUB(max(date), INTERVAL 2 DAY) AND DATE_ADD(max(date), INTERVAL 1 DAY)

when this returns '2015-01-20' and '2015-01-19'?:

SELECT date 
FROM hours 
HAVING date BETWEEN '2015-01-18' AND '2015-01-21'

max date is '2015-01-20' and there are records on both '2015-01-20' and '2015-01-19'. date is a date field.

I think you'll find that date_sub returns a full time stamp eg '2008-11-11 13:23:44.657' see http://www.w3schools.com/sql/func_date_sub.asp for more details.

You'll want to use the extract method or date_format ( DATE_FORMAT(date_time_var, '%Y-%m-%d') ) to get just the day, month and year as used in your between statement.

Your first example contains aggregate functions. HAVING typically requires a GROUP BY, because it's a means to filter groups. So putting GROUP BY date before HAVING date will get you both the 19th and 20th (for your first SQL statement).

That's HAVING behaviour.

HAVING will group results in your first query because there is a grouping function MAX in HAVING clause. All returned rows will be grouped in one row-group because there is no GROUP BY instruction. Therefore, you only get one result. date value of this group can be any of the grouped rows.

HAVING will do no group in second query because there is no grouping function in HAVING clause, nor GROUP BY instruction.

Adding a GROUP BY date as suggested will group rows that have the same date ; hence MAX will only return that date value instead of MAX of all dates. So, you will retrieve all rows because MAX(date) == date in all grouped rows.


SELECT `date`, GROUP_CONCAT(`date`), (SELECT MAX(`date`) FROM `hours`) AS `md`
FROM `hours`
GROUP BY `date`
HAVING `date`
BETWEEN DATE_SUB(md, INTERVAL 2 DAY) AND DATE_SUB(md, INTERVAL 1 DAY);

You might also use

SELECT `hours`.`date`, `md`.`d`
FROM `hours`, (SELECT MAX(`date`) AS `d` FROM `hours`) AS `md`
WHERE `hours`.`date`
BETWEEN DATE_SUB(`md`.`d`, INTERVAL 2 DAY) AND DATE_ADD(`md`.`d`, INTERVAL 1 DAY);

Not sure which one is the fastest...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM