I have an event listing site where i'm currently listing events occuring today by doing:
def load_today_events
#today_events = Event.find(:all, :conditions => ['start_date =?', Date.today])
end
This works perfectly well.
I've recently introduced an end_date for events spanning more than one day.
Obviously, with the above code once the start_date has passed the event disappears from my listing.
I may be having a mental block here, but I can't for the life of me figure out how to show events that's start date has passed but end date has not.
I think I want something along the lines of:
find events where date.today is equal to or between start_date or end_date
Any ideas how best to approach this?
Not sure if i understand this correctly, but here are some examples of what you can do with dates.
In the example below, current_date is a postgresql function for the today date. This would match the events that the current_date is bigger or equal than start_date and less than end_date.
#today_events = Event.where("current_date >= ? and current_date <= ?", start_date, end_date)
Another approach could be like this:
#today_events = Event.where("start_date >= ? and end_date <= ?", start_date, end_date)
This example shows events that are from a current date interval.
This is the basics, so i hope you can apply to your own problem.
Related
i am trying to get all records within a date range in rails that fall after a given start date and before a given end date, ignoring the year. the start date will just be a month. the end of the date range is a month and date.
the following example is to get users with a hire date month equal to january or greater, but less than 2(february) / 28(day).
i was trying this but it doesnt work:
users.where('extract(month from hire_date) >= ?', 1).where('extract(month from hire_date) <= ? AND extract(day from hire_date) <= ?', 2, 28)
the reason this doesnt work is it will exclude users, for example who fall on 1/29, because their day in january is not less than 28.
is there a good way to make this work, ignoring the year on the date field?
I would use to_char to transform the dates into strings including just the month and the day. For example 2021-12-31 could be translated into "12-31". That string can then be compared to the range of date strings you are interested in.
users.where("to_char(hire_date, 'MM-DD') BETWEEN '01-01' AND '02-29'")
Note that this, in theory, this would also match invalid date strings like '01-40'. But I guess it is safe to assume that to_char with a valid date will never return such invalid date strings.
Let me start by saying that I'm not familiar with ruby-on-rails, sql, or activerecord but this question really piqued my interest because it contains a number of complexities that I've never had to deal with. Most notably:
How to accommodate leap years when the test range and target date may
have differing leap year statuses.
How to deal with a hire date of February 29th. This may seem to be
the same as the first item on my list, but it has its own unique
nuances.
How to deal with ranges that started in one year and then overlap into the next.
I did some searching myself and there seems to be very little information out there on the subject, particularly any that seems to properly deal with the various complexities listed above, so I decided to see if I could come up with a logical approach of my own. It seems like it may be a novel approach, but ultimately I decided that converting month and day to float values would allow an easy way to address the leap year issue as well as the issue with February 29th, and that testing the date ranges using an if/else statement along with opposing boolean operations would solve the ranges that overlap years.
You may have to extrapolate and reconfigure for your specific needs, but here's the general idea written out in pure ruby. It's rather verbose, but I did so just to try and make it more clear what I'm doing. I could be made much more compact:
hire_date = Time.new(2004, 1, 22)
provided_start_date = Time.new(2008, 12, 22)
day_value = (60*60*24) #60 seconds * 60 minutes * 24 hours = 1 day
num_days = 30
calculated_end_date = provided_start_date + num_days*day_value
start_range = provided_start_date.month + provided_start_date.day/100.0
end_range = calculated_end_date.month + calculated_end_date.day/100.0
day_float = hire_date.month + hire_date.day/100.0
if start_range < end_range
result = day_float >= start_range and day_float <= end_range
else
result = day_float >= start_range or day_float <= end_range
end
result
So i figured out something that worked for this.
given the following:
start_date = 01 Jan 2021
end_date = 02 Feb 2021
Users.where("(extract(month from hire_date) * 100 + extract(day from hire_date)) BETWEEN ? AND ?", ((start_date.month * 100) + start_date.day), ((end_date.month * 100) + end_date.day))
start date and end date can be any dates and this should work to get all users between, since SQL between is inclusive, it will also get users whos end and start dates fall on the start / end date, ignoring year.
I have a table in which I have emails to users and I want to make request to take users who are dated less than two days from today. How can make this?
This is my SQL table :
CREATE TABLE vacation_users(EMAIL VARCHAR(255), STARTDATE DATE, ENDDATE DATE);
The answer is this. I use HSQLDB and this is answer.
SELECT * FROM vacation_user WHERE (ENDDATE < (SYSDATE + 2 DAY));
Try this(not tested):
SELECT EMAIL from vacation_users
WHERE ENDDATE < DATEADD(day, +2, CURRENT_DATE) AND ENDDATE > CURRENT_DATE
It selects the mails, which have the enddate, which is equal bigger than current date, but smaller than current date + 2.
EDIT: I updated the answer, since the OP informed me about the DB, which is used. If CURRENT_DATE also doesn't work, you can try another from the built-in functions.
select *
from vacation_users
where STARTDATE = dateadd(day,datediff(day,2,STARTDATE),0)
That depends on a database you use, but the principle is more or less the same.
In Oracle, you'd do something like
select email
from vacation_users
where startdate < sysdate - 2;
which returns you to exact time 2 days ago (if it is 09:53 today, it'll be 09:53 2 days ago). Depending on what you really need, you might need to TRUNCate those values (so that you'd get date without its time component) or apply some other function or principle, regarding possible index impact etc.
Though, "dated less than two days from today" is ... what exactly? Is it a STARTDATE or ENDDATE (or some combination of those two)?
SELECT *
FROM vacation_users
WHERE (DATEADD(day,2,ENDDATE)) < (CONVERT(date, SYSDATETIME()))
I'm having trouble setting up a SQL to bring up all information 2 weeks before and after the current date. Here is what I am currently doing:
Select WRK.Wrk, WRK.Client, WRK.Status, WRK.TAT, WRK.Due
From WRK
WHERE WRK.Due >= now()
Order By WRK.Due Desc, WRK.Status Desc
This gets me everything due on or after the current date but when I try to add lines to indicate 2 weeks before and after the current date I get errors.
Thanks
Date/time function vary significantly among databases. The use of now() makes me think of MySQL. The syntax in MySQL is:
where wrk.Due between date_sub(curdate(), interval 2 weeks) and date_add(curdate, interval 2 weeks)
Note that between includes the end dates, so this might be off by a day in either direction.
You can implement similar logic in other databases, but the specific functions would look different.
What I am trying to do is to select a specific month and a specific day from a timestamp. What I have tried is this:
SELECT t FROM test WHERE t BETWEEN '2015-08-01 00:00:00' AND '2015-08-01 23:59:59';
with 8 being the specifc month and 1 being the specific day but this doesn't return anything.
Another thing I would like to do is to choose a specific day of every month of the year what I have tried that I know is wrong but I am not sure how else to do it is:
SELECT t FROM test WHERE t BETWEEN '2015-01-12 00:00:00' AND '2015-24-12 23:59:59';
I can see why this wouldn't work as I take every timestamp from the day in the first month to the same day in the last month, but how can I do it?
edit: I found why it wasn't working for the first example the variable i had for day contained a number so when it was lower than 10 it only said # and not 0#
You could just use a LIKE clause for this. Also your between won't work for edge cases if you have milliseconds after :59.
WHERE t LIKE '2015-08-01 %'
and:
WHERE t LIKE '2015-%-12 %'
Also, regarding optimization, timestamp or similar has text affinity (even though the docs seem to allude to it being numeric). It should allow for like optimization if you have an index, but using ranges will likely be better if you can manage it. I would check the query plans.
I have a table in a database with one column containing dates and another one containing scores. Basically, what I want to do is grab the best score in a given week.
Weeks can start on any given day (From Friday to Thursday, for instance), and that is defined by the user.
Here is what I have so far:
SELECT MAX(Series), DATE(DATE(Date, 'weekday 0'), '-7 days') dateStartOfWeek FROM SeriesScores
WHERE Season = '2010-2011'
AND dateStartOfWeek = '2010-08-29'
GROUP BY DateStartOfWeek
Where Series is the column containing the scores and Date is the (badly) named actual date.
The problem with this query is that it works for every day except for the day the week is supposed to be starting on.
For example: 2010-08-29 is a Sunday and in this example, I'm trying to find on which date the Sunday of the given week is. My function works for every day of that week except for 2010-08-29 (Sunday) since it tries to find the next day that is a Sunday (itself in this case). To compensate for that, I go back 7 days to get the correct Sunday, which creates the error for the already correct Sunday since this one doesn't need to go back 7 days or else it is one week off.
I figured I could solve this problem easily using Java, but I want to see how it should be done using SQL instead.
My solution (I don't even know if it can be done), would be to check if date and dateStartOfWeek are the same. If they are, don't substract 7 days from the date. If they're not, do as I did in my example. I don't know how to use conditions such as this one in SQL, though, and this is where I need help.
Thanks a lot in advance!
I think you need to use CASE operator - see http://sqlite.awardspace.info/syntax/sqlitepg09.htm
EDIT - try:
SELECT MAX(Series), CASE WHEN STRFTIME ( '%w', Date ) = 0 THEN DATE(Date, 'weekday 0') ELSE DATE(DATE(Date, 'weekday 0'), '-7 days') END AS dateStartOfWeek FROM SeriesScores
WHERE Season = '2010-2011'
AND dateStartOfWeek = '2010-08-29'
GROUP BY DateStartOfWeek
see http://www.sqlite.org/lang_datefunc.html