where clause with time columns on sql server - asp.net

In the project there a functionality that lets you book the place during the day, they have to enter the day, the start time and final time from 7:00 am to 12:00 AM (midnight) or 1:00 AM, for example if someone enter date=21/oct/2011 start time=8:00 pm and end time 12:00 am (he book the place from 8:00 pm until 12:00 am) the webform send to the store procedure 20:00 and 00:00 to check the table to see if is available, if someone already book in the same day until midnight it is store like this
startime=23:00 endtime=00:00
so when i check the new client it has to return that there a reservation already in the range of time,
my query is not efficient but it working from the 7:00 to 23:00 range, it fails when from the webfrom enters a endtime 12 am (00:00 on sql) because the starttime es greater than the end time
this is my query
select COUNT(*)
from table1
where id_place=#id_place
and date=#date
and (
(#start_time=res_start_time and #end_time=res_end_time)
or (#start_time > res_start_time and #start_time < res_end_time)
or (#end_time > res_start_time and res_end_time < res_end_time)
or (res_start_time > #start_time and res_start_time < #end_time)
or (res_end_time > #start_time and res_end_time < #end_time)
or (res_start_time < #start_time and res_end_time >#end_time)
)
-- #start_time = start time of the reservations (from webform)
-- #end_time = end time of the reservations (from webform)
-- res_start_time= represents the start time column
-- res_ebd_time= represents the end time column
i need help on two things, how i solved the issue when i have to check times like 12:00 am or 1:00 am that are already in the table like the example at the begins of the question and to check my query because is think there has to be a better solution to implement this kind of functionality

You obviously have a date somewhere in the table, as well, or you would not be able to book resources. This leads to a couple of possibilities.
Query both time and date (can get complex, but you can make this a udf for reuse)
Use DateTime instead of date and time columns
if in SQL Server, consider creating a CLR function to handle this, as the CLR (.NET code) will more efficiently determine "is in time range"
I am sure there are other possibilities. The key point here is it sounds like your algorithm is failing largely due to events that spill over to another day. If that is correct, bring the day into the equation is your best bet. This can end up as a rather complex SQL statement, a change of data types (datetime instead of date and time) or creating a .NET function (CLR) to help more efficiently determine "is in range".

Related

Ms-Access convert datetime to seconds since epoch [duplicate]

I'm trying to write a query for an MS Access 2007 connection to a MySQL database through ODBC. Everything's working fine, and the query does what I want it to do. The part that I'm hung up on is that I'm stuck asking the user for unix epoch time, instead of a regular date.
I looked up a bunch of references for MS Access, and while there are a number of date conversion functions I can use in the SQL call, I can't find any that I can use to convert from a normal date -> unix epoch date.
What I would like, and I assume this works, is to ask the user for the date in a much kinder fashion (a human readable date), and then convert it into unix epoch date. Now that I think about it, I guess my other option is to convert the unix epoch dates in the database after drawing them out with the SQL query, but I'd rather convert the user's input if at all possible as there is less of that input so I wouldn't have to do as much work.
SELECT TOP 5 Count( * ) AS [Number of visits by language], login.lang AS [Language]
FROM login, reservations, reservation_users
WHERE (reservations.start_date Between [Starting unix epoch time] And [Ending unix epoch time]) And reservations.is_blackout=0 And reservation_users.memberid=login.memberid And reservation_users.resid=reservations.resid And reservation_users.invited=0
GROUP BY login.lang
ORDER BY Count( * ) DESC;
Don't know if this is going to work (don't have Access to confirm), but try the suggestion from here:
http://weblogs.sqlteam.com/jeffs/archive/2007/04/13/format-date-sql-server.aspx
which is to use:
DATEDIFF(second, '1 Jan 1970', tbl.LastChangeDate)
This is from some of the comments.
EDIT: See the comment from Remou.
Using MS 2010 I found this works: DateAdd("s",([epoch timestamp]-21600),#1/1/1970#)
http://www.pcreview.co.uk/forums/convert-epoch-date-t2324318.html

Searching between 2 different time periods

I would like to be able to have a stored procedure that will allow the user to search between 2 different time frames based off of a parameter that will say whether they are searching for results on a full 24 hour period or based off the business hours. Would a case statement in the where clause be the best choice? This will be a stored procedure that will be used in an SSRS report and the user will choose between "Calendar Day" and "Business Day" in a drop-down menu to specify the type of day defined by the parameter in the stored procedure. Thank you for any help.
I don't know if you'd need to use a CASE statement in your WHERE clause. You could probably just get away with ANDs and ORs.
WHERE
(Parameter = 'Calendar Day')
or
(Parameter = 'Business Day' and DATEPART(HOUR, DateField) between 9 and 17)
The where clause won't compare the hour when its a calendar day but when it's a business day, the time needs to be between 9 am and 5 pm.

Retrieve date from Evernote date_created timestamp field

Does anyone know on what basetime Evernote calculates datetime?
I need to directly deal with the notes table in the Evernote SQLite DB and the documentation refers people to the SQLite manual https://www.sqlite.org/lang_datefunc.html
This stored time 736012.8334375 should yield 2016/02/18 21:00
I've tried multiple variants such as
select datetime(((((736012.8334375)*1000/60)/60)/24), 'unixepoch'), datetime(((736012.8334375)), 'unixepoch'), datetime(736012.8334375, 'unixepoch'), strftime('%s', 'now'), strftime('7736012.8334375', 'unixepoch'), datetime((736012.8334375 *1000), 'unixepoch')
giving
"1970-01-01 23:39:46","1970-01-09 12:26:52","1970-01-09 12:26:52","1464341058",,"1993-04-28 16:00:33"
This Excel formula
=((((736012.8334375)*1000/60)/60)/24)+DATE(1970,1,1)+(1/24)
gets closer with
4/28/93 5:00 PM
but still a bit out.
What am I doing wrong?
Here's the formula I arrived at for determining the real date from Evernote's dates:
unixTime = (EvernoteTime * 86400) - 62135683200
I've tested this with a few time zones by exporting data from the Evernote app to html and hand-verifying the times match.
I'm not sure where the 62135683200 comes from. It's not quite the difference between unix epoch and year zero, but after arriving at the correct value I stopped trying to figure it out.

SQLite Query Sorting

I'm a bit of a nub when it comes to SQL queries and I couldn't find any help so I figured I'd ask.
I'm currently working on an event tracker/calendar style thing, with two types of events. One is a standard starts at X and ends at Y, while the other is "all day" (ie, starts at 12:01 AM, ends at 11:59 PM). My problem is the database query to sort it properly. What I'm trying to do is get the return such that the all-day events are at the very end of that day's list.
For example, if I have 4 events, one at 1 PM, one at 2 PM, one all day, and one tomorrow at 11 AM, it would look like:
1:00 PM Event
2:00 PM Event
All Day Event
Tomorrow 11:00 AM Event
I've got UNIX timestamps (in seconds for whatever reason) for start and end dates, and my current attempt is
SELECT * FROM table ORDER BY all_day_flag, startTime;
This won't work, because it would always put the all-day events at the end, so any tips on where to refine it would be much appreciated.
You need to extract the date and time separately from your Unix timestamp, and then use the date as the first sort option, followed by all-day flag and then the time.
Try this:
SELECT date(startTime, 'unixepoch') AS startDate,
time(startTime, 'unixepoch') AS startHour,
time(endTime, 'unixepoch') AS endHour,
all_day_flag
FROM table
ORDER BY
startDate, all_day_flag, startHour;

SQL - Hours of operation

I'm having a hard time wrapping my head around what seems to be a somewhat simple issue. Let's say that I have a business whose hours are 12PM - 3AM daily. Each customer gets a bonus once per day based on their initial purchase for that day. So, let's say they spend twenty bucks on their first transaction that day -- they might get a twenty percent discount on that transaction, and that's it for the day.
I'm trying to figure out the most accurate way to check the last bonus that was given and make sure that the customer is eligible for one. I can't do a simple 24-hour check, obviously, because if a customer comes in at 11 PM Monday, for instance, and again at noon Tuesday, they will not get their second bonus.
We are using a VB6 frontend for our POS, with a SQL Server 2008 R2 database. Each time a bonus is applied, it is audited on the database side, so I can easily query the last time the bonus was applied.
EDIT: I should note that, for various reasons, the solution cannot include making any changes to the structure of the database.
I'm not sure on which side (VB or SQL) you want to apply the biz logic but in either case the process should be the same: You need to persist each customer's daily hours of operation with two attributes:
Time (the time of day that they open for business)
TimeSpan (number of hours of operation)
You then check if a transaction's time is between Time and Time + TimeSpan to calculate your business logic and the customer's bonus. Both calculations are fairly trivial in VB and SQL. You just need to make sure you persist the data logically and use it consistently.
I think your answer would be cleaner if you modified it to something like:
IF #LastBonus BETWEEN #store_open AND #store_close
BEGIN
SET #BonusDue = 0
END
ELSE
BEGIN
SET #BonusDue = 1
END
where you figure the store open and close dates based on a fixed times that are added to the date part of the last bonus. Something like
Set #openTime = '12:00'
Convert(date, #LastBonus) + #openTime
And then adding the timespan (as was suggested) to get the close time. It might be a little tricky because if it's after midnight, the open time would need to be added to the previous date instead, but you could probably work this out with a CASE statement. I'd try it out myself if my baby didn't have an ear infection. Hope that is useful to you.
How about:
IF (DATEPART(dayofyear, [lastBonusTime]) <> DATEPART(dayofyear, GetDate())) ...
Where lastBonusTime is the time of the last bonus transaction ?
You can look at the problem a bit differently. If a customer is here now (GETDATE()), has it been over 24 hours since their last purchase?
So, something like
SELECT *
FROM Customers c
INNER JOIN CustomerVisits cv
ON c.CustomerId=cv.CustomerId
INNER JOIN CustomerBonus cb
ON cv.VisitId=cb.VisitId
WHERE c.CustomerId=#CustomerId
AND LastVisitDt BETWEEN
(
DATEADD(hh,12,convert(DATE, LastVisitDt))
)
AND
(
DATEADD(hh,27,convert(DATE, LastVisitDt))
)
AND DATEADD(hh,24,LastVisitDT)<=GETDATE()
I would also consider the specifics of the data--the above is NOT TUNED FOR PERFORMANCE AT ALL. I just wanted to explain my thought process.
In the interest of separating your concerns, I would add a new table, like CUSTOMER_BONUS, with these columns:
BonusStart datetime
BonusEnd datetime
CustomerID int/uniqueidentifier/whatever
TransactionID int/whatever (points to what qualified for the bonus)
When you apply a bonus for a customer for a day, write a new record into this table for the period that it applies to. Presence of a record in this table indicates that the customer is not eligible for another bonus between BonusStart and BonusEnd. When you create a new sale, look in this table. If the record exists, no bonus, but if not, apply the bonus and create a new record here.
I came up with an answer that I'm content with but it's a little kludgy and I would be more than happy to accept a more elegant answer if one is provided. Also, I haven't thoroughly tested this since it's getting late in the day, but if there are flaws in my logic, I will happily revise or accept an answer with revisions.
Basically, I'm just going to determine that the day of the week in terms of a business day is whatever day started four hours ago. This means that all the way up through 3:59 AM, "today" will be considered the day before, which is correct for these hours of operation (I'm overshooting the 3 AM closing time to account for a site deciding to stay open a little later). I then compare this span of time to the most recent time a bonus was applied to that customer's account, using the same rules. If the two match, the bonus has been applied this business day. If they are different, it has not, and the customer is eligible.
DECLARE #CustID AS int
DECLARE #LastBonus AS date
DECLARE #BonusDue AS bit
SET #LastBonus = (SELECT TOP 1 [DateTime] FROM Audit WHERE CustomerID = #CustID AND TransactionType = 'BONUS' ORDER BY [DateTime] DESC)
IF (SELECT DATEADD(hh, -4, CURRENT_TIMESTAMP)) <>
(SELECT DATEADD(hh, -4, #LastBonus))
BEGIN
SET #BonusDue = 1
END
ELSE
BEGIN
SET #BonusDue = 0
END
If I throw this in a stored procedure, I can simply throw a customer ID at it and have it spit out a bit that will show me 1 if the customer is eligible, 0 otherwise. What I don't like about it is that if a customer's hours of operation end up getting much earlier, I'll be sunk (I guess at about 7:00 AM, when simply subtracting four hours will overlap into the previous business day, but subtracting less will not be enough to reach the previous business day). So it will work for the time being, but I'd love to see a better solution.

Resources