Intersect between two date intervals - mysql

I need to find intersect between to date intervals for example
I have one date
2015-01-01 and 2015-03-01
and second value
2015-01-01 and 2015-01-15
I wanna get results 15. So how many days of second date is included in first date range?
Any ideas how to do it with MySql?

In MySQL you can use the following SQL statement to get what you need:
SELECT DATEDIFF(LEAST('2015-03-01 23:59:59','2015-01-15 23:59:59'),GREATEST('2015-01-01 00:00:00','2015-01-01 00:00:00'))+1 AS days;
+------+
| days |
+------+
| 15 |
+------+
This will get the date difference in days using DATEDIFF

You can use CASE for condition like below:
SELECT (CASE
WHEN '2015-01-01'>= '2015-01-01' AND '2015-04-15'<='2015-03-01'
THEN DATEDIFF('2015-01-15','2015-01-01')+1
ELSE 'out of range'
END) AS days;
You can specify your own else condition and date range.

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 |
+----+-------------+----------+--------+-------------+

mysql between 2 dates does not working with 2 different months

Hello i need expert advice for my mysql query
I'm trying to filter values between 2 months
If start day lower then end day of different months all working well
But if i try higher day value on start return none
this is working code
SELECT id, teslim_tarihi AS tarih, toplam, marka, model, malzeme
FROM ariza
WHERE durum = '7' AND (teslim_tarihi BETWEEN '01-02-2018 00:00' AND '01-03-2018 23:59')
ORDER BY tarih DESC
Not working at all
SELECT id,teslim_tarihi as tarih ,toplam,marka,model,malzeme
FROM ariza
WHERE durum = '7' AND (teslim_tarihi BETWEEN '14-02-2018 00:00' AND '01-03-2018 23:59')
ORDER BY tarih DESC
date format dd-mm-yyyy H:i
As has been suggested by #stackFan, it really does make considerable sense to stick with mysql's default date and time formats. However, for whatever reason, you seem to be stuck with a different format so I'll attempt to work with that.
Your current query isn't working in your second example because mysql doesn't recognise these as dates and a strings starting '14-02-2018' is greater than another string starting '01-03-2018'. e.g.
SELECT '14-02-2018' > '01-03-2018';
+-----------------------------+
| '14-02-2018' > '01-03-2018' |
+-----------------------------+
| 1 |
+-----------------------------+
The values when using BETWEEN ... AND have to have the min value first and the max value Documentation, so in your second example the comparison is the wrong way round because '14-02-2018' is greater than '01-03-2018', hence no rows returned.
You didn't answer the query about the data type of your column teslim_tarihi which would have made answering your query simpler. I'll assume it is a DATETIME or TIMESTAMP. Your comparison should be made against something that mysql knows to be a date or recognises as a date and that means getting the dates into YYYY-MM-DD or YY-MM-DD format. Mysql will helpfully cast values to the appropriate type if the format is one it recognises. e.g.
SELECT DATE '2018-02-14' < '2018-03-01';
+-----------------------------------+
| DATE '2018-02-14' < '2018-03-01' |
+-----------------------------------+
| 1 |
+-----------------------------------+
You should be able to get the query working by turning your strings into dates in the following manner.
SELECT DATE '2018-03-01'
BETWEEN STR_TO_DATE('14-02-2018 00:00', '%d-%m-%Y %H:%i')
AND STR_TO_DATE('01-04-2018 23:59','%d-%m-%Y %H:%i') 'between dates';
+---------------+
| between dates |
+---------------+
| 1 |
+---------------+
If your column teslim_tarihi is a VARCHAR, then convert that in the same manner to get the query to work.
As per the documentation the default format of date in MySQL is YYYY-MM-DD. Can you try using this query instead?
SELECT id,teslim_tarihi as tarih ,toplam,marka,model,malzeme
FROM ariza
WHERE durum = '7' AND (teslim_tarihi BETWEEN '2018-02-14 00:00:00' AND '2018-03-01 23:59:59')
ORDER BY tarih DESC

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

How to get data from date and time range in MySQL

MySQL Table: -
ID | From_DateTime | To_DateTime
1 2014-09-01 10:00:00 2014-09-10 22:00:00
Explanation:
I have added 2 columns in database table for Date and Time range. The data shown above means that from 01-09-2014 to 10-09-2014 is the date range and 10:00:00 to 22:00:00 is the time range.
Positive Scenario - Now I am passing 2014-09-05 15:00:00 in my query which comes into Date and Time both range. What I need is the ID from the query.
Negative Scenario - Now I am passing 2014-09-05 23:00:00 in my query which comes into Date comes into range but TIME is not in the specified range so I should get 0 result.
I have no idea about database queries and that is why I am posting it to here to get some help from the database experts.
Something like this should work. May need some tweaking.
SELECT ID FROM (
SELECT ID FROM <tablename>
WHERE DATE('<dateTimeValue>') BETWEEN DATE(From_DateTime) AND DATE(To_DateTime)
AND TIME('<dateTimeValue>') BETWEEN TIME(From_DateTime) AND TIME(To_DateTime)
UNION
SELECT 0 AS ID FROM DUAL
) AS a LIMIT 1
SELECT id FROM date_time
WHERE From_DateTime < '2014-09-05 15:00:00'
AND To_DateTime > '2014-09-05 15:00:00';
here date_time is table name...
Don't forgot to put date in single quotes

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.