Mysql Between in Between - mysql

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');

Related

Dynamic due dates checking with the given period of dates

id start_date interval period
1 1/22/2018 2 month
2 2/25/2018 3 week
3 11/24/2017 3 day
4 7/22/2017 1 year
5 2/25/2018 2 week
the above is my table data sample. start_dates will be expired based on interval and period(i.e id-1 will have due date after 2 months from the start_date, id-2 will have due after 3 weeks vice versa). period is enum of (day,week,month,year). Client can give any period of dates. let's say 25-06-2026 to 13-07-2026 like that.. I have to return the ids whose due dates falls under that period.I hope i made my question clear.
Here what i have done to resolve this. I am using mysql 5.7. I found ways to achieve this with recursive CTE's.(not available in mysql 5.7). and there is a way to achieve this by populating virtual records by using inline sub queries along with unions and its a performance killer and there is restriction of population of records.(like given in the link Generating a series of dates) I have reached a point to get results for a single date which is very easy. Below is my query(in oracle)
select id
from (select a.*,
case
when period='week'
then mod((to_date('22-07-2018','dd-mm-yyyy')-start_date),7*interval)
when period='month' and to_char(to_date('22-07-2018','dd-mm-yyyy'),'dd')=to_char(start_date,'dd')
and mod(months_between(to_date('22-07-2018','dd-mm-yyyy'),start_date),interval)=0
then 0
when period='year' and to_char(to_date('22-07-2018','dd-mm-yyyy'),'dd-mm')=to_char(start_date,'dd-mm')
and mod(months_between(to_date('22-07-2018','dd-mm-yyyy'),start_date)/12,interval)=0
then 0
when period='day'
and mod((to_date('22-07-2018','dd-mm-yyyy')-start_date),interval)=0
then 0 else 1 end filter from kml_subs a)
where filter=0;
But I need to do this for a period of dates not a single date. Any suggestions or solutions will be much appreciated.
Thanks,
Kannan
Assuming this is an Oracle question and not MySQL:
I think the first thing that you need to do is calculate when the due date is. I think a simple case statement can handle that for you:
case when period = 'day' then start_date + numtodsinterval(interval,period)
when period = 'week' then start_date + numtodsinterval(interval*7,'day')
when period = 'month' then add_months(start_date,interval)
when period = 'year' then add_months(start_date,interval*12)
end due_date
Then, using that new due_date field, you can check if the due date falls between the desired date range.
select *
from(
select id,
start_date,
interval,
period,
case when period = 'day' then start_date + numtodsinterval(interval,period)
when period = 'week' then start_date + numtodsinterval(interval*7,'day')
when period = 'month' then add_months(start_date,interval)
when period = 'year' then add_months(start_date,interval*12)
else null end due_date
from data)
where due_date between date '2018-02-25' and date '2018-03-12'
The above query checking between 2/25/18 and 3/12/18 produces the following output using your data:
+----+-------------+----------+--------+-------------+
| id | start_date | interval | period | due_date |
+----+-------------+----------+--------+-------------+
| 2 | 05-FEB-2018 | 3 | week | 26-FEB-2018 |
| 5 | 25-FEB-2018 | 2 | week | 11-MAR-2018 |
+----+-------------+----------+--------+-------------+

Return rows between two dates

I have ItemsRent table,
ID | ParentID | SubID | StartDate | EndDate |
--------------------------------------------------------------------
1 | 100 | 102 | 2014-09-09 17:40:00 | 2014-11-09 17:40:00 |
2 | 70 | 73 | 2014-08-09 14:20:00 | 2014-12-09 13:40:00 |
The dates are in sql format.
My input dates are:
InputStartDate: 2014-09-09 18:00:00
InputEndDate: 2014-10-09 13:47:00
And i want to return the best row only of the dates are between two dates. So for example:
Lets call StartDate as S, and EndDate as E.
And input dates will be InputStartDate as IS, and InputEndDate as IE.
S E
|----------------|
IS IE
|XXXXXXX--------|
Any suggestions ?
This query will produce a result matching your illustration. It will find all rows where any time at all was spent between InputStartDate and InputEndDate, and output a modified date range that is clamped by InputStartDate and InputEndDate.
SELECT ID, ParentId, SubId,
MAX( InputStartDate, StartDate ) AS Date_Start,
MIN( InputEndDate, EndDate ) AS Date_End
FROM `itemsRent`
WHERE InputStartDate <= EndDate AND InputEndDate >= StartDate
Normally, I would say to use the BETWEEN operator, but since you are storing both the start and end dates in the table, this would get more complicated than it needs to be. If you assume that the start date being stored is before the end date, you only need to perform two checks.
SELECT * FROM `itemsRent` WHERE `StartDate` > 1410285600 AND `EndDate` < 1410356820
This verifies that the start date of the item takes place after the specified start date. The issue with this is that it does not check if it takes place before the end date. Instead of explicitly writing this check, you can make sure of this by checking that the item's end date takes place before the specified end date.
NOTE: Might cause issues if the start date does not occur before the end date. If this is a possibility, then you will need to explicitly write these checks. This would be a good case in which to use the BETWEEN operation.
Why not just pull out the max end date in the table as the high date?
SELECT *
FROM itemsRent
WHERE (InputStartDate BETWEEN startdate AND end date)
AND (InputEndDate BETWEEN startdate AND enddate);
Your query is currently looking for rows whose EndDate is earlier than your provided StartDate or after your provided EndDate. I don't think that is what you want.
If you want rows that both StartDate and EndDate are between your provided dates (lets call them your-start-date and your-end-date), your query should be something like:
SELECT * FROM `itemsRent` WHERE `StartDate` > your-start-date AND `StartDate` < your-end-date AND `EndDate` > your-start-date AND `EndDate` < your-send-date

MySQL Query for certain date range

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 &plus; 3 &plus; 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)

Count number of Distinct days in query

We have a table that has a StartDate field which holds a type of datetime. There are thousands of records and I am looking for a way to find the number of days within a given result returned from this table. For instance, if my table had this data:
ID | StartDate
--------------
1 01/01/2013 09:34:54
2 01/01/2013 11:23:21
3 04/11/2013 14:43:23
4 04/11/2013 17:13:03
5 04/25/2013 18:02:59
6 07/21/2013 02:56:12
7 10/01/2013 19:43:10
Then the query should return 5 as the 2 dates on 01/01/2013 count as 1 and the same for 04/11/2013.
The only SQL I've been able to come up with is:
SELECT COUNT(DISTINCT(DATEPART(DAY, StartDate)))
FROM Stats
WHERE StartDate BETWEEN '01/01/2013' AND '12/31/2013' --This is just for filtering
But this returns 4 because it doesn't take the month into account.
Any help is appreciated.
You can CAST as date
SELECT COUNT(DISTINCT CAST(StartDate AS DATE))
FROM Stats
WHERE StartDate >= '20130101' AND StartDate < '20140101'
Also use an unambiguous date format such as yyyymmdd and >= < not BETWEEN.
Your current query would include the 31st December if there was a row with exactly the value 20131231 00:00:00 but not any with different times on that date. I doubt that is intentional.

Access 2007 query to capture records that encompass 2 dates

I'm working on a query to get records based on two dates, start and end dates.
What I need to obtain are records that are span some or all of the given period, in other words the start date maybe before the parameter date but less than the end date or start after the start date and end after the end date.
I.e. Start date = 01 Oct 12 and end date 31 Oct 12. I would like to capture records where start date is before 1 Oct but spans this period whether it finishes in November or mid October. As well as records that are between 01 Oct 12 and 31 Oct 12.
In reality I need the records that exclude this period, but first need to make sure I'm getting this dataset correct.
I'm starting with this simple data set stored in MyTable, with both start_date and end_date as Date/Time data type.
id start_date end_date
1 9/29/2012 9/30/2012
2 9/29/2012 10/2/2012
3 9/29/2012 11/1/2012
4 10/2/2012 11/1/2012
5 11/1/2012 11/2/2012
Running the query below, and supplying 2012-10-01 and 2012-10-31 for the range_start and range_end parameters, gives me this output result set.
id start_date end_date
2 9/29/2012 10/2/2012
3 9/29/2012 11/1/2012
4 10/2/2012 11/1/2012
If this is not similar to what you wanted, please edit your question to show us a brief sample set of input data and the output you want from that sample.
Also, note the time components of my start_date and end_date values were all midnight. If your counterparts include any other times of day, you will need to revise the query to deal with them.
This is the SQL from the query I used:
PARAMETERS range_start DateTime, range_end DateTime;
SELECT m.id, m.start_date, m.end_date
FROM MyTable AS m
WHERE
m.start_date Between [range_start] And [range_end]
OR m.end_date Between [range_start] And [range_end]
OR (m.start_date<[range_start] AND m.end_date>[range_end]);