i'm having the following table data:
Table: Seasons
id from to
---------------------------
1 2013-08-30 2013-09-04
2 2013-09-05 2013-09-08
3 2013-09-09 2013-09-20
i need to run a query which returns all records which are within a certain date range, for example: return all records which are affected from 2013-09-04 to 2013-09-05
it would be like
date range: | 09-04 - 09-05|
seasons: 08-30 - 09-04 | 09-05 - 09-08 | 09-09 - 09-20
so it should return the first 2 records.
i've tried the query with BETWEEN but it seams i need to build up several cases - or is there a simpler way?
thankx
It's amazing no one has noticed this for almost two years, but the other answers are all wrong because they didn't take into account the case when both the start date and the end date fall beyond the scope of the search range. Consider this is the range of the date:
start_date <<---------------------------- date range --------------------------->> end_date
And this is the range of our search:
start_date <<---------------------------- date range --------------------------->> end_date
start_search <<-------- search range -------->> end_search
The search should give us a positive result because they intersect. But if you use the other answers, you would get a negative result because neither start_date nor end_date is between start_search and end_search.
To get the solution, let's draw all 4 possible modes of intersection:
start_date <<---------- date range --------------------------->> end_date
start_search <<------------------------- search range -------->> end_search
start_date <<---------------------------- date range ---------->> end_date
start_search <<---------- search range ------------------------>> end_search
start_date <<---------------------------- date range --------------------------->> end_date
start_search <<-------- search range -------->> end_search
start_date <<----------- date range -------->> end_date
start_search <<------------------------- search range ------------------------>> end_search
You can OR all 4 possible cases to obtain the straightforward solution:
select*from table where
/* 1st case */ start_date between start_search and end_search
or /* 2nd case */ end_date between start_search and end_search
or /* 3rd case */ (start_date <= start_search and end_date >= end_search)
or /* 4th case */ (start_date >= start_search and end_date <= end_search)
/* the 4th case here is actually redundant since it is being covered by the 1st and 2nd cases */
A less straightforward solution is:
select*from table where
start_date between start_search and end_search /* covers 1st and 4th cases */
or start_search between start_date and end_date /* covers 2nd and 3rd cases */
Try to visualize it using the diagrams above.
If we attempt to extrapolate a pattern out of the 4 diagrams above, we can see that during an intersection, end_date is always >= start_search, and on the flip side, start_date is always <= end_search. Indeed, visualizing further, we can see that when those two conditions hold, we cannot not have an intersection.
As such, another solution is as simple as:
select*from table where
end_date >= start_search && start_date <= end_search
And the advantage of this solution is that we only need 2 comparisons. Contrast that with the "OR everything" approach which requires from 2 up to as much as 8 (3 + 3 + 2) comparisons. (Each between call consists of 3 comparisons.)
Try with:
SELECT *
FROM `Seasons`
WHERE (`from` BETWEEN '2013-09-04' AND '2013-09-05' OR `to` BETWEEN '2013-09-04' AND '2013-09-05')
This should work
SELECT *
FROM `Seasons`
WHERE (date_field BETWEEN '2010-01-30 14:15:55' AND '2010-09-29 10:15:55')
**Make sure that the date is in mysql default formate (yyyy-mm-ff hh:mm:ss)
Related
Assume table contains the following columns name, created_at which string and date types.
Looking for any help to make a SQL query that outputs rows within any 30-day range where there are at least 5 or more rows that has the created_at column of the table inside that range.
The query can just output the rows or the last one in the range - whichever is easy.
The 30-day range can start from today and go backwards or from the first row forward etc.
created_at can be grouped if required.
I think this is an aggregation query with filtering:
select name, max(created_at)
from t
where created_at >= #start - interval 30 day and
created_at < #start
group by name
having count(*) >= 5;
I am building out a query to search a table by a timestamp column value. An example of the format I am passing to the api is 2018-10-10. The user has the ability to select a date range. Often times the date range start date is 2018-10-10 and end date is the same day, 2018-10-10. The below doesn't seem to do the trick. What is the simplest way to accomplish this without having to specify the time? Obviously, I'd like to query for the entire day of 2018-10-10 from start to end of day.
SELECT
count(*)
FROM
contact
WHERE
created_at >= '2018-10-10'
AND created_at <= '2018-10-10';
The problem here is that Timestamp datatype will have HH:MM:SS (time) values also. While comparing a datetime with date, MySQL would automatically assume 00:00:00 as HH:MM:SS for the date value.
So, 2018-10-10 12:23:22 will not match the following condition: created_at <= '2018-10-10'; since it would be treated as: 2018-10-10 12:23:22 <= '2018-10-10 00:00:00, which is false
To handle this, you can add one day to the date (date_to in the filter), and use < operator for range checking.
SELECT
count(*)
FROM
contact
WHERE
created_at >= '2018-10-10'
AND created_at < ('2018-10-10' + INTERVAL 1 DAY);
I have the following data in the table
from_date to_date
2015-05-12 2015-10-20
2015-10-21 2016-02-02
2016-02-03 NULL
Where NULL value in to_date denotes that this record is valid until this time.
The records I want to retrieve is between '2015-10-30' and '2016-08-08'. How do I get the second and third rows based on my search criteria?
I am confused why are you expecting the second row in the result set. Is it something loose range searching (either by from_date or by to_date)?
You can try something like that:
SELECT
*
FROM your_table
WHERE from_date >= startDate
AND IF(to_date IS NULL, TRUE, to_date <= endDate);
Note: Here startDate and endDate are the dates in your given range.
EDIT:
SELECT
*
FROM your_table
WHERE
'2015-10-30' BETWEEN from_date AND COALESCE(to_date,CURDATE())
OR
'2016-08-08' BETWEEN from_date AND COALESCE(to_date,CURDATE())
Finally, I found out what I was looking for.
select * from table where
end_date >= start_search && start_date <= end_search
More detailed answer in the link below. Answered by pacerier
mysql-query-for-certain-date-range
This sql with mysql db does not work:
SELECT *
FROM `house1_rent_2014`
WHERE MONTH( `FIRST_OF_MONTH` ) = MONTH( NOW() )
AND DATE_ADD(MONTH(`FIRST_OF_MONTH`,INTERVAL 15 DAY) <= CURDATE();
what I want to do is get all the current month vales from the column FIRST_OF_MONTH (that works OK by itself) and then add the additional test if it's a current month value of course in the date field and today's date is greater than the 15th of the current month then select that. In other words a field has 2014-09-01 (again, I only want date fields with the current month) if today is 9/15 or later then select it.
I'm getting mixed up w/syntax and perhaps proper logic. Grateful for help
The syntax you have is way more convoluted than it needs to be, and I think the specification is overly confusing too.
"get all the current month vales from the column FIRST_OF_MONTH"
Did you want to return values from September of last year too? (The MONTH() function only returns the month value (1 thru 12), and doesn't include the year, which seems a bit odd.
To get rows for the "current month", we'd typically do something like this:
WHERE t.first_of_month >= DATE_FORMAT(NOW(),'%Y-%m-01')
AND t.first_of_month < DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL 1 MONTH
Predicates on a "bare column" allow MySQL to make effective use of an index, in this case, a range scan of an index with leading column of first_of_month. If we wrap those columns in a function, then MySQL has to evaluate the function on every row on the table.
"then add the additional test if it's a current month value of course in the date field and today's date is greater than the 15th of the current month then select that."
You already have a predicate that checks for dates in the "current month", there's no need to repeat that.
This predicate will evaluate to TRUE if the current date is after the 15th, and will return FALSE if the current date is the 15th or earlier.
AND DATE(NOW()) > DATE_FORMAT(NOW(),'%Y-%m-15')
Examples
If we have these rows in the table:
row first_of_month
--- --------------
1 2014-09-30
2 2014-10-02
3 2014-10-14
4 2014-10-16
5 2014-10-31
6 2014-11-01
If we run a query with these predicates:
WHERE t.first_of_month >= DATE_FORMAT(NOW(),'%Y-%m-01')
AND t.first_of_month < DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL 1 MONTH
AND DATE(NOW()) > DATE_FORMAT(NOW(),'%Y-%m-15')
If DATE(NOW()) returns '2014-10-11', then the third predicate will evaluate to FALSE, and no rows will be returned.
If DATE(NOW()) returns '2014-10-16', then all of the rows with first_of_month in the current month are returned, that is, rows 2 thru 5 in the example data.
If DATE(NOW()) returns '2014-11-07', then third predicate is false, and no rows are returned.
If DATE(NOW()) returns '2014-09-25', the query will return row 1 in the example data.
how to select data between 2 dates in between 2 dates? for example :
start_date - end_date -- title
2014-01-28 2014-02-03 test
2014-02-01 2014-02-15 ests
2014-02-28 2014-03-03 sets
2014-03-01 2014-03-10 sste
the problem is, i want to select data between 2014-02-02 and
2014-02-28 with first three of them selected because the first three
data is included on 2nd month.
i tried this, but not works
SELECT title FROM my_tables WHERE start_date BETWEEN 2014-02-02 AND 2014-02-28
how it works?
Two periods overlap when one begins before the other ends, and the other ends after the first begins. Here is the correct logic:
SELECT title
FROM my_tables
WHERE start_date <= '2014-02-28' and
end_date >= '2014-02-02';
Note that date constants need to be in single quotes.
Here is a SQL Fiddle showing it working.
Add single quote to date constant
SELECT title FROM my_tables WHERE start_date BETWEEN '2014-02-02' AND '2014-02-28'
A date range overlaps with another when either the start or the end is within that other range:
given range: |----|
range 1 |----| overlaps with given range, because end_date is in that range
range 2 |----| overlaps with given range, because start_date is in that range
range 3 |----| does not overlap with given range, because both start and end date are not in that range
SELECT title FROM my_tables
WHERE (start_date BETWEEN '2014-02-02' AND '2014-02-28')
OR (end_date BETWEEN '2014-02-02' AND '2014-02-28');