Query to see if subscription is active between two date ranges - mysql

I have a table that stores seasonal address dates:
addressStartDate, addressEndDate
I'm trying to find people whose seasonal addresses were historically active in May, but I'm not quite sure how to format it. I just can't seem to conceptualize how to build the query based on the two date fields. The "was active" part is the part I'm having issues with.
The years for the dates in this case are all stored as 1000, since the seasonal address switch happens at the same time every year. So what I'm looking for is people whose addresses were active between DATE '1000-05-01' and DATE '1000-05-31' - I hope this suffices to describe my issue

Try this
SELECT *
FROM yourtable
WHERE addressStartDate >= '1000-05-01'
AND addressEndDate <= '1000-05-30'

Perhaps:
SELECT *
FROM mytable
WHERE addressStartDate <= ? AND addressEndDate <= ?

Are you looking for something like this:
SELECT addressStartDate, addressEndDate, otherfields
FROM yourTable
WHERE addressStartDate >= '1000-05-01'
AND addressEndDate < '1000-06-01'
Or depending on the interpretation of your question, if an address date just needs to exist in the month, perhaps something like this:
SELECT addressStartDate, addressEndDate, otherfields
FROM yourTable
WHERE addressStartDate < '1000-06-01'
AND addressEndDate >= '1000-05-01'
Depending on how you're storing your data (with or without time), instead of using BETWEEN, I prefer using >= and < as needed.

If you want active for the whole month of May, then:
select *
from t
where t.StartDate <= date('1000-05-01') and t.StopDate >= date('1000-05-31')
If you want active for any days in May:
select *
from t
where t.StartDate <= date('1000-05-31') and t.StopDate >= date('1000-05-01')
The StopDate limits may be off by one, depending on whether or not the date of the stop date is considered an active date.
This may also be complicated by whether your data goes by the calendar year, because you have a problem with your data structure. StartDate can be larger than StopDate, which would imply a year wrap. To handle year wraps, try this:
select *
from t
where (t.StartDate < t.StopDate and t.StartDate <= date('1000-05-01') and t.StopDate >= date('1000-05-31')) or
(t.StartDate > t.StopDate and ( t.StartDate <= date('1000-05-01') or t.StopDate >= date('1000-05-31')))

Related

Why this WHERE condition that have to select records in a specified timeframe is not working as expected?

I am not so into database and I have the following problem working on this MySql query:
SELECT
CCMD.id AS crop_calendar_message_details_id,
CCMD.broadcasting_start_date AS broadcasting_start_date,
CCMD.broadcasting_end_date AS broadcasting_end_date,
CCMD.creation_date AS creation_date,
CCM.id AS message_id,
CCM.content_en AS content_en,
IFNULL(CCMN.content, CCM.content_en) AS content,
CCMN.audio_link AS audio_link,
CCMD.crop_action_details_id AS crop_action_details_id
FROM CropCalendarMessageDetails AS CCMD
INNER JOIN CropCalendarMessage AS CCM
ON CCMD.crop_calendar_message_id = CCM.id
LEFT JOIN CropCalendarMessageName AS CCMN
ON CCMN.crop_calendar_message_id = CCM.id AND CCMN.language_id = :language_id
INNER JOIN CropActionDetails AS CAD
ON CCMD.crop_action_details_id = CAD.id
WHERE
CCMD.commodity_id = 10
AND
CCMD.country_id = 2
AND
CAD.id = :cad_id
AND
CCMD.broadcasting_start_date >= CURDATE()
AND
CURDATE() <= CCMD.broadcasting_end_date
ORDER BY CCMD.broadcasting_start_date
I have some records that have the following fixed values for thes date fields:
CCMD.broadcasting_start_date = 22/12/2018 23:59:00
CCMD.broadcasting_end_date = 30/05/2018
So in theory my query should skip these values because I have set this section on my WHERE clause:
AND
CCMD.broadcasting_start_date >= CURDATE()
AND
CURDATE() <= CCMD.broadcasting_end_date
The problem is that these records are returned by my query so this dates filter condition is not working.
Why? What is wrong? What am I missing? How can I fix it?
When dealing with date/time values and querying, I personally have always tried to apply >= and < the boundaries. For example, if you wanted something for All activity within March, 2018, I would do
where '2018-03-01' <= DateTimeField
AND DateTimeField < '2018-04-01'
By doing greater or equal to the start of just a date, you get from midnight all the way through the date period. As for the ending date, I always go LESS than the following day (hence April 1st). So I get everything up to Mar 31 at 11:59:59pm.
This way you also dont need to mess with date conversion functions just to ensure something is on the same day or time-portions thereof.
Might this help in resolving the date/time considerations of your query.

Date and Time MySQL Statement

I have two fields, "cont_time_published" and "cont_date_published" that I want to use to filter results in a listing of records.
select *
from news
WHERE cont_date_published < CURDATE() AND cont_time_published < CURTIME()
I am trying to achieve listing that only shows records that the publish time and publish date is in the past. So that it would filter a record that has today's date but the time is still in the future.
Results are wrong when the date is today and the time is future.
cont_date_published is "DATE" only field and cont_time_published is "TIME" Field.
If you need to get the records published in the past (today in the past hours or before) try:
SELECT *
FROM news
WHERE cont_date_published < CURDATE()
OR (cont_date_published = CURDATE() AND cont_time_published < CURTIME());
sorry my mistake, forgot the OR
Try this
SELECT *
FROM news
WHERE (cont_date_published < CURDATE() ) AND ( cont_time_published < CURTIME() )
ORDER BY id DESC;
You can CAST to an actual date:
WHERE CAST(CONCAT(cont_date_published, ' ', cont_time_published) AS DATETIME)<NOW()
... but this will possibly prevent query optimiser from using indexes (if any). An alternative would be:
WHERE cont_date_published<CURDATE() OR
(cont_date_published=CURDATE() AND cont_time_published<CURTIME())
Of course, all this extra work could be easily avoided with a proper database design that makes use of a single DATETIME column:
WHERE cont_published<NOW()
select * from news WHERE cont_date_published < CURDATE()
This will be enough to get the records that are Published in the Past.

My join sql query won't bring results

What could be wrong with my sql query here , I'd like to retrieve data from both tables meeting a WHERE condition
SELECT *, UNIX_TIMESTAMP(i.sent_date) AS udate
FROM ibc_sent_history as i INNER JOIN
ibc_messages as u
ON i.msg_ids = u.id
WHERE (i.sent_date >= '02-02-2013' AND i.sent_date <= '02-02-2014')
ORDER BY i.sent_date
LIMIT 200
Assuming your ibc_sent_history.sent_date datatype is DATETIME, here's a way to refactor this query. (This will work even if the datatype is DATE). You need to change your date input string format from 02-02-2013 to the more standard '2014-02-02` (YYYY-MM-DD).
SELECT whatever, whatever
FROM ibc_sent_history AS i
INNER JOIN ibc_messages AS u ON i.msg_ids = u.id
WHERE i.sent_date >= '2013-02-02'
AND i.sent_date < '2014-02-02' + INTERVAL 1 DAY
ORDER BY i.sent_date DESC
LIMIT 200
I changed the ORDER BY to include DESC. This is to return the most recent items, not the oldest. If that's not what you need, take off the DESC.
I changed the date formatting.
I changed the end of your selection range to
i.sent_date < '2014-02-02` + INTERVAL 1 DAY
That's because
i.sent_date <= '2014-02-02`
will include items that occur precisely at midnight on 2-Feb-2014, but won't include any other items on that day. What you probably want are items that occurred up to but NOT including midnight on the next day.
I don't know MySQL very well, but in SQL Fiddle when I run:
CAST('2014-02-02' AS DATE)
I get a date, when I run
CAST('02-02-2014' AS DATE)
I get NULL, so seems like your date format is wrong.
Demo: SQL Fiddle

How to check if selected date range is between another date range

I am in the situation where i want to match a date range with another date range, it might be simple but i am stuck at it.
Below is table structure
Table - lifecycles
life_id
life_start_date
life_end_date
then a few records as below
1 - 07/23/2013 - 07/24/2013
2 - 07/15/2013 - 07/25/2015
3 - 03/10/2013 - 03/10/2014
Now i want to search these records by date range and want to see if some life exists in that range; e.g. i want to find the lives between 08/01/2013 - 01/01/2014
As expected result it should select the life#2 and life#3
How can this be done with MySQL query?
Any help is highly appreciated.
This query should do it:
SELECT
*
FROM
lifecycles
WHERE
str_to_date(life_start_date, '%m/%d/%Y') <= '2014-01-01'
AND str_to_date(life_end_date, '%m/%d/%Y') >= '2013-08-01';
Which basically means life hasn't started before the end of the range you are looking for, and life didn't end before the range start.
Since you keep dates in VARCHAR format, you need to use str_to_date function, which is bad since MySQL won't be able to utilize any possible indexes you have on start_date or end_date columns.
This might help you.
SELECT SUM( IF( '2014-01-02' BETWEEN from_date AND to_date, 1, 0 ) ) AS from_exist,
SUM( IF( '2014-02-12' BETWEEN from_date AND to_date, 1, 0 ) ) AS to_exist
FROM date_range
So based on the results you can check whether date is between existing date range or not.
So you want to exclude lifes that are ended BEFORE 08/01/2013 and the ones that are not started AFTER 01/01/2014. This should work:
SELECT *
FROM lifecycles as alive
WHERE NOT EXISTS (
SELECT 1
FROM lifecycles as dead
WHERE dead.life_id = alive.life_id
AND (str_to_date(life_start_date, '%m/%d/%Y') > '2014-01-01'
OR str_to_date(life_end_date, '%m/%d/%Y') < '2013-08-01'))

How to use where clause in separate datetime(year,month,day)

http://upic.me/i/hq/capture.png
http://upic.me/i/3g/capture.png
I have the table that divide datetime to single field and set these field to index.
i would to use where clause in date range ex. between 2010/06/21 to 2011/05/15
I try to use
where concat_ws('-',year,month,day) between '2010/06/21' and '2011/05/15'
it's work because I use concat function to adjust these field like ordinary datetime
but it not use index and query slowly.This table has 3 million record
if would to use index I try to this query
where
year = '2011'
and month between 05 and 06
and day between 21 and 15
It almost work but in last line
day between 21 and 15
I can't use this condition
I try to solve this problem but I can't find it and change structer table
I'm looking for answer
thank you
Now I can OR operation for query thank for your answer
In another case if would to find 2009/08/20 to 2011/04/15 It's use longer query and make confusion.Has someone got idea?
If it's a datestamp type, you can just use the where/between clause directly. I would consider switching to that, it's quite faster than a varchar with a custom date format.
WHERE yourdate BETWEEN "2011-05-01" AND "2011-06-15"
Although checking ranges may work for single months, you will find if you're querying between several months to have some margin of error because, if you think about it, you're selecting more than you may necessarily want. Using Datestamp will fix performance and usability issues arising from storing the date in a custom varchar.
Here are the two queries to convert your times around if you're interested:
ALTER TABLE `yourtable` ADD `newdate` DATE NOT NULL;
UPDATE `yourtable` SET `newdate` = STR_TO_DATE(`olddate`, '%Y/%m/%d');
Just change "yourtable", "newdate", and "olddate" to your table's name, the new date column name, and the old datestamp column names respectively.
If you can't change the table structure, you could use something like the following:
WHERE year = '2011'
AND ((month = '05' AND day >= 21) OR (month = '06' AND day <= '15'))
(At least, I think that query does what you want in your specific case. But for e.g. a longer span of time, you'd have to think about the query again, and I suspect queries like this could become a pain to maintain)
UPDATE for the updated requirement
The principle remains the same, only the query becomes more complex. For the range of 2009/08/20 to 2011/04/15 it might look like this:
WHERE year = '2009' AND (month = '08' AND day >= '20' OR month BETWEEN '09' AND '12')
OR year = '2010'
OR year = '2011' AND (month BETWEEN '01' AND '03' OR month = '04' AND day <= '15')
where year = 2011
and (month between 5 and 6) and (day > 20 or day < 16)
You where seperating days and month whereas you must keep them together
parentheses must be set ...
Mike
It is important that you use OR otherwise it is nonsense