MySQL query to fetch result between start date and end date - mysql

I have two dates say start_date = 2013-04-12 and end_date = 2013-04-30
and my table contains row with start_date = 2013-04-12 and end_date = 2013-04-16
I want to fetch records whose start date is greater 2013-04-12 and end_date is less than 2013-04-30. Which includes above record having 2013-04-16 as end_date
I tried with this query
SELECT * FROM TABLE_NAME WHERE (start_date <='2013-04-12' AND end_date >='2013-04-30') which dont give any result however if i put end_date 2013-04-15 it works fine

SELECT
*
FROM
(
SELECT
'2013-04-12' as `start_date`,
'2013-04-16' as `end_date`
) `sub`
WHERE
(`start_date` BETWEEN '2013-04-12' AND '2013-04-30')
AND
(`end_date` BETWEEN '2013-04-12' AND '2013-04-30')
BETWEEN is more reliable

If you want to have start_date GREATER OR EQUAL 2013-04-12 and end_date LESSER OR EQUAL, than your operators are wrong:
start_date <='2013-04-12' AND end_date >='2013-04-30'
you should use >= for start_date and <= for end_date
like this:
start_date >='2013-04-12' AND end_date <='2013-04-30'

I think you are using wrong operators ... start_date greater than(>=) end_date less than equal to (<=)
SELECT * FROM TABLE_NAME WHERE (start_date >='2013-04-12' AND end_date <='2013-04-30')

I would do:
SELECT * FROM table_name WHERE start_date BETWEEN '2013-04-12' AND '2013-04-30'

Try this,
SELECT * FROM TABLE_NAME WHERE Convert(varchar,start_date,101) >'04/12/2013') AND convert(varchar,end_date,101) <'04/30/2013')

Related

How to order by dates with time periods with current date first then future time periods and then past time periods?

I have a table with columns ID, START_DATE and END_DATE. What I want to do is to execute a query which orders the resulting rows in the following order:
If the current date is 2020-12-14 then the result should be
START_DATE END_DATE
2020-12-8 2020-12-18 -----> Time periods which contains current day and are ordered by start_date in ASCENDING order.
2020-12-9 2020-12-15
2020-12-10 2020-12-17
2020-12-15 2020-12-17 -----> Time periods with START DATE > current date and are ordered by start_date in ASCENDING order.
2020-12-16 2020-12-22
2020-12-21 2020-12-25
2020-12-9 2020-12-13 ----->Time periods with END DATE < current date and are ordered by start_date in DESCENDING order.
2020-12-6 2020-12-8
2020-12-1 2020-12-9
How can I accomplish this?
You need in something similar to
ORDER BY CASE WHEN CURRENT_DATE BETWEEN start_date AND end_date
THEN 1
WHEN start_date > CURRENT_DATE
THEN 2
ELSE 3 END,
CASE WHEN end_date > CURRENT_DATE
THEN start_date + 0
ELSE DATEDIFF(CURRENT_DATE, start_date)
END
fiddle
start_date + 0 needed for to convert the result of this CASE to numeric. Without it the CASE alternatives combines date and numeric values which causes the final datatype to be a string - with wrong sorting order.
You can use conditional ordering as follows:
Select * from your_table
Order by
case when CURRENT_DATE between start_date and end_date OR start_date > CURRENT_DATE
then 1
When end_date < CURRENT_DATE
then 2
end,
case when CURRENT_DATE between start_date and end_date or start_date > CURRENT_DATE
then date_diff(start_date, CURRENT_DATE)
When end_date < CURRENT_DATE
then date_diff(CURRENT_DATE,start_date)
end
In MySQL, I would write this as:
order by (curdate() between start_date and end_date) desc,
(curdate() > curdate()) desc
case expressions are not needed because MySQL treats boolean values as a number, with 1 for true and 0 for false.

How to set variable in mySQL

I have the following statement:
SELECT
start_date,
end_date,
DATE(now()) BETWEEN start_date AND end_date should_be_live
FROM
mytable
WHERE
DATE(now()) BETWEEN start_date AND end_date should_be_live = 1
Is there a way to set a variable should_be_live = the expression DATE(now()) BETWEEN start_date AND end_date. If so, how would I do this?
If by "variable" you mean "column in the result set", then yes. You are basically doing it:
SELECT start_date, end_date,
( DATE(now()) BETWEEN start_date AND end_date) as should_be_live
FROM mytable;
If by "variable", you mean that you want to define a column in the select and then filter on it, you cannot do that with where (unless you use a subquery). You can use having:
SELECT start_date, end_date,
( DATE(now()) BETWEEN start_date AND end_date) as should_be_live
FROM mytable
HAVING should_be_live = 1;
This use of having is a MySQL extension.
No unfortunately, you will have to repeat the same expression DATE(now()) BETWEEN start_date AND end_date in your WHERE clause unless you are trying to access it in a outer query like
SELECT * FROM (
SELECT
start_date,
end_date,
DATE(now()) BETWEEN start_date AND end_date as should_be_live
FROM mytable ) xxx
WHERE should_be_live = 1;
Column alias are accessible only to GROUP BY, HAVING and ORDER BY clause and not to WHERE clause (that to it's a MySQL extension and not standard SQL)

Using mysql to query dates that fall between 2 other dates

I have a table that has a field 'start_date' and also a field 'end_date'. Items are considered active when the current date is between 'start_date' and 'end_date'. How would I find all the items that would be considered active for the next 30 days.
Assuming start_date and end_date are DATETIME, and you want to compare the date AND time components, you could do something like this:
SELECT a.*
FROM atable a
WHERE a.start_date >= NOW()
AND a.end_date <= NOW() + INTERVAL 30 DAYS
If start_date and end_date are DATE (rather than DATETIME), you probably only want to compare the DATE portion (without regard to a time component)
SELECT a.*
FROM atable a
WHERE a.start_date >= DATE(NOW())
AND a.end_date <= DATE(NOW()) + INTERVAL 30 DAYS
You may actually want a less than comparison (rather than less than or equal to) on the end date. You need to determine what results you want on that edge case. And the interval may need to be specified as 29 days, depending on how you define "the next 30 days".
Q: What about items that started before NOW and will run for the next 30 days?
A: I think I understand what you were asking.
I think you are wanting to retrieve any rows where the any point in time between the start_date and end_date falls anytime between now and 30 days from now. I can see that my query above does not answer that question.
For now, I'm going to consider only cases where " start_date < end_date ", and shelve cases where start_date is not less than end_date, or where either start_date or end_date or both are NULL.
We can depict the possible cases something (rather crudely) like this:
The vertical bars represent NOW and NOW+30
The less than sign represents "start_date"
The greater than sign represents "end_date"
The dashes represent the range of DATETIME betwen start_date and end_date
NOW NOW+30
<---> | | case 1: end_date < NOW()
<---|----> | case 2: NOW() between start_date and end_date
<--|-------|----> case 3: NOW() > start_date and NOW+30 < end_date
| <---> | case 4: both start_date and end_date between NOW() and NOW()+30
| <--|---> case 5: start_date between NOW() and NOW()+30 and end_date > NOW+30
| | <---> case 6: start_date > NOW()+30
<---> | case e1: end_date = NOW()
<--|-------> case e2: start_date > NOW() AND end_date = NOW()+30
<---> | case e3: start_date = NOW() and end_date < NOW()+30
<-------> case e4: start_date = NOW() and end_date = NOW()+30
<-------|--> case e5: start_date = NOW() and end_date > NOW()+30
| <---> case e6: start_date > NOW() AND end_date = NOW()+30
| <---> case e7: start_date = NOW()+30
I think you are asking to return rows that satisfy cases 2 thru 5, which is all cases EXCEPT for case 1 and 6.
If we can write a predicate that tests for cases 1 and 6, and then negate that, it should give us what you want. Something like this:
To handle datetime with time component considered:
WHERE NOT ( end_date < NOW() OR start_date > NOW() + INTERVAL 30 DAYS )
if start_date and end_date are DATE, to compare just the DATE portion, wrap the NOW() function in the DATE() function:
WHERE NOT ( end_date < DATE(NOW()) OR start_date > DATE(NOW()) + INTERVAL 30 DAYS )
I shelved the oddball cases, of start_date > end_date, start_date = end_date, start_date IS NULL, end_date IS NULL, etc. I also omitted discussion of the edge cases (e1 thru e7), e.g. start_date = NOW(), end_date = NOW(), etc. For completeness, you probably want to check whether those cases are handled appropriately with this same predicate.
DOH!
It just dawned on me that this:
WHERE NOT ( a < n OR b > t )
is equivalent to this (at least for not null values)
WHERE ( a >= n AND b <= t )
So this predicate should be equivalent:
WHERE end_date >= NOW() AND start_date <= NOW() + INTERVAL 30 DAYS

Is Today Between Two (DATETIME) Columns? (empty or all zeroes count as unbound upper/lower limit)

I have a table of products and two DATETIME columns, one for start_date and one for end_date.
How do I check if a specific product ID is between the start date and end date? However, if one or both of these is NULL (the default value) accept this lower/upper bound to be unlimited and return the product if it's still within the other bound (if it's set). If both bounds are set to NULL always return the product.
select *
from your_table
where
product_id = 1 AND
(
(CURDATE() between start_date and end_date)
or (CURDATE() >= start_date and end_date is null)
or (CURDATE() <= end_date and start_date is null)
or (start_date is null and end_date is null)
)
select case when ('2012-06-26' between start_date and end_date)
or ('2012-06-26' >= start_date and end_date is null)
or ('2012-06-26' <= end_date and start_date is null)
then 1
else 0
end as is_between_dates
from your_table
where product_id = 1

MySQL, get data between start and end date columns?

I've read a few similar questions then mine, where I could find queries that were pretty much the same I'm using. But I had to ask, because I would like to understand why this is not working:
I have the following data:
id category_id start_date end_date image campaign_id published
1 1 2011-07-05 2011-07-5 a.gif 3 1
2 1 2011-07-01 2011-07-15 c.gif 3 1
3 37 2011-07-01 2011-07-04 d.gif 3 1
I expect to get rows 1 and 2, from this query:
SELECT id, category_id, start_date, end_date FROM categories_campaigns WHERE start_date <= NOW() AND end_date >= NOW();
From what I've experienced, the only row returned is the second. Also this one, gives me the second,
SELECT category_id, start_date, end_date FROM categories_campaigns WHERE end_date >= NOW();
The next one returns me all 3,
SELECT category_id, start_date, end_date FROM categories_campaigns WHERE start_date <= NOW();
The datatype for both columns are DATE. So, my question is, how to solve this ? Why is this happening ? Or I've got an obvious error that I'm not finding on what to look for.
Working query
SELECT
category_id, start_date, end_date
FROM
categories_campaigns
WHERE
start_date <= DATE(NOW()) and end_date >= DATE(NOW());
I think you could use this:
SELECT category_id, start_date, end_date FROM categories_campaigns WHERE left(now(),10) between start_date and end_date;
I suppose start_date and end_date are of date datatype. But NOW() returns a date-time value.
Use CUR_DATE() instead of NOW()