Comparing Time in SQL Server 2008 - sql

Here is my table. I need a query which returns the shift id for a specified time
How can I get the value?
shift_ID shift_From shift_To
1 2010-09-21 10:00:00.000 2010-09-21 18:10:00.000
2 2010-09-21 20:00:00.000 2010-09-21 05:00:00.000
Suppose I am giving 02:00:00 as input I need to get the shift ID as 1. How can I do this?

Try:
SELECT shift_ID
FROM time_shift
WHERE
DATEDIFF(hour, shift_From, shift_To) = 2 -- your input
See more about DATEDIFF on MSDN
The first argument is the time part you're specifying to DATETIFF (hour, minute, second).
If your input is strictly like 02:00:00 you need to parse it to determine what specify as the first argument.
To determine does the specified date belong between 2 others, use:
SELECT shift_ID
FROM time_shift
WHERE
CAST(shift_From AS TIME) < CAST(#input AS TIME)
AND
CAST(#input AS TIME) < CAST(shift_To AS TIME)
-- you can specify operators inclusiveness, i.e. <= >= etc
-- or
CAST(#input AS TIME) BETWEEN (CAST(shift_From AS TIME), CAST(shift_To AS TIME))
See more about TIME on MSDN

Related

Extract Date And Hour Only From Date Time Field

I am running SQL Server 2008 and I have a datetime field, from this field I only want to extract the date and hour. I tried to parse out using datepart() but I think I did it incorrectly as when I attempted to string the two back together I got a number value. What I attempted was
Select Datepart(YEAR, '12/30/2015 10:57:00.000') +
Datepart(HOUR, '12/30/2015 10:57:00.000')
And what was returned was 2025 What I want to see returned is
12/30/2015 10:00:00.000
You could use DATEADD and DATEDIFF:
DECLARE #d DATETIME = '12/30/2015 10:57:00.000';
SELECT DATEADD(second,DATEDIFF(second,'1970-01-01',#d)/3600*3600 , '1970-01-01')
-- 2015-12-30 10:00:00
LiveDemo
How it works:
Get seconds difference from 1970-01-01
Divide by 3600 (integer division so the part after decimal point will be skipped)
Multiply by 3600 to get value back to full hours
Add calculated seconds number to 1970-01-01
With SQL Server 2012+ the neat way is to use DATETIMEFROMPARTS:
SELECT DATETIMEFROMPARTS(YEAR(#d), MONTH(#d), DAY(#d), DATEPART(HOUR, #d),0,0,0)
LiveDemo2

T-SQL : convert(datetime) to include/exclude certain hours

Using date range to select values, but also need to use an hour range to determine if a record should be selected. The date ranges and time ranges are not necessarily associated.
game_time (between 6 am and 6 pm)
have tried straight between statement and datepart, but cannot get anything to capture what we need.
create table gametime(name varchar, start_time datetime, end_time datetime)
insert assorted name, start_times and end_times
Desired results
name start_time end_time
name1 8:00 AM 10:00 AM
name2 8:00 AM 11:30 AM
name3 4:00 PM 5:30 PM
name4 6:00 PM 9:00 PM
datetime is used is storage, but not needed in presentation.. only times are needed in presentation.
Selected games should only start between the hours of 6:00 AM and 6:00 PM.
Any and all suggestions and insight appreciated......
Using
LTRIM(RIGHT(CONVERT(VARCHAR(20), start_time, 100), 7))
to get the correct format for presentation,
but when I try to use
LTRIM(RIGHT(CONVERT(VARCHAR(20), start_time, 100), 7)) > 6
I get conversion errors.
I would use DATEPART rather than relying on converting to/comparing strings:
WHERE DATEPART(hour,start_time) BETWEEN 6 AND 18
Try CONVERT(VARCHAR(5),start_time,108) BETWEEN '06:00' AND '18:00'. Right now you're trying to compare a string to an integer.
Here's another way, provided you're on SQL Server 2008 or higher and have the TIME type available:
SELECT *
FROM gametime
WHERE CAST(start_time AS TIME) BETWEEN '06:00:00' and '18:00:00'
This can be a bit more flexible when your time range is not anchored to exact hours. It also is sarg-able -- i.e. it will use an index, where calling DATEPART will prevent that.

Time Difference in Redshift

how to get exact time Difference between two column
eg:
col1 date is 2014-09-21 02:00:00
col2 date is 2014-09-22 01:00:00
output like
result: 23:00:00
I am getting result like
Hours Minutes Seconds
--------------------
3 3 20
1 2 30
using the following query
SELECT start_time,
end_time,
DATE_PART(H,end_time) - DATE_PART(H,start_time) AS Hours,
DATE_PART(M,end_time) - DATE_PART(M,start_time) AS Minutes,
DATE_PART(S,end_time) - DATE_PART(S,start_time) AS Seconds
FROM user_session
but i need like
Difference
-----------
03:03:20
01:02:30
Use DATEDIFF to get the seconds between the two datetimes:
DATEDIFF(second,'2014-09-23 00:00:00.000','2014-09-23 01:23:45.000')
Then use DATEADD to add the seconds to '1900-01-01 00:00:00':
DATEADD(seconds,5025,'1900-01-01 00:00:00')
Then CAST the result to a TIME data type (note that this limits you to 24 hours max):
CAST('1900-01-01 01:23:45' as TIME)
Then LTRIM the date part of the value off the TIME data (as discovered by Benny). Redshift does not allow use of TIME on actual stored data:
LTRIM('1900-01-01 01:23:45','1900-01-01')
Now, do it in a single step:
SELECT LTRIM(DATEADD(seconds,DATEDIFF(second,'2014-09-23 00:00:00','2014-09-23 01:23:45.000'),'1900-01-01 00:00:00'),'1900-01-01');
:)
SELECT LTRIM(DATEADD(seconds,DATEDIFF(second,'2014-09-23 00:00:00','2014-09-23 01:23:45.000'),'1900-01-01 00:00:00'),'1900-01-01');

Sql query to get range of values

I have a table called TimeList
SlotID SlotStartTime SlotEndTime
(int identity) (varchar(10)) (varchar(10))
1 8:00AM 8:15AM
2 8:15AM 8:30AM
3 8:30AM 8:45AM
4 8:45AM 9:00AM
5 9:00AM 9:15AM
6 9:15AM 9:30AM
7 9:30AM 9:45AM
8 9:45AM 10:00AM
If I am passing SlotStartTime and SlotEndTime I want to get times in between.
I used the following query to get timeslots in b/w slotStarttime 8:00AM amd slotEndTime 9:00AM
select * from TimeList1 where StartTime >='8:00AM' and EndTime <= '9:00AM'
Here the result is coming as:
SlotID SlotStartTime SlotEndTime
1 8:00AM 8:15AM
2 8:15AM 8:30AM
3 8:30AM 8:45AM
8 9:45AM 10:00AM
I want to get slotstarttime starting from 8:00AM and slotendtime ending 9:00AM means
expected result is:
SlotID SlotStartTime SlotEndTime
1 8:00AM 8:15AM
2 8:15AM 8:30AM
3 8:30AM 8:45AM
4 8:45AM 9:00AM
What change do I have to make in my query to get the result as above?
When you're using varchars (or strings in most languages), you'll find that "10:00" < "9:00" just because of character sequencing rules (since "1" < "9").
You should be storing date and time values in date and time columns. If you must use varchars, you'll need to convert them to fixed-size 24-hour format to do it properly (e.g., "01:30", "12:15", "18:25").
But my advice is to store them as proper DB date and time values. Your queries will be easier and faster.
The following solution may get you what you want if I understand your data storage (one entry per quarter hour) but my professional opinion is to fix the column types, since that will allow for far more expressive conditions in your select statements:
select * from TimeList1
where left(StartTime,1) = '8'
and right(StartTime,2) = 'AM'
Part of the problem, as has been noted, is that you are using strings to represent times. The other part of your problem is that the AM/PM notation is completely ghastly for computational purposes. Remember, the sequence is:
12:00AM
12:15AM
12:30AM
12:45AM
1:00AM
1:15AM
...
9:45AM
10:00AM
10:15AM
...
11:30AM
11:45AM
12:00PM
12:15PM
12:30PM
12:45PM
1:00PM
1:15PM
...
The 24-hour clock has many merits. If you used:
00:00
00:15
00:30
00:45
01:00
01:15
...
09:45
10:00
10:15
...
11:30
11:45
12:00
12:15
12:30
12:45
13:00
13:15
...
(for the same set of numbers) then your VARCHAR strings could be made into CHAR(5) and would automatically sort correctly in time sequence. You would still have to phrase your queries correctly, including the leading zero(es) on times less than 10:00, but the values would sort correctly and compare correctly.
Some DBMS provide support for sub-sets of time. In IBM Informix Dynamic Server, you could use DATETIME HOUR TO MINUTE as the type for the column. That would give you back the flexibility of dropping leading zeroes.
See also Convert 12-hour date/time to 24-hour date/time.
Your query is correct. But it's your data types that are wrong.
10:00AM indeed comes before 9:00AM considering they are string, not datetime values.
So if you can't change the data types now, your best luck is to try this query :
Select * from TimeList1
where StartTime >= Cast('8:00AM' as datetime)
and EndTime <= Cast('9:00AM' as datetime)
//make sure StartTime and EndTime is type of datetime
Try this:
SELECT *
FROM TimeList1
WHERE (CONVERT(datetime, CONVERT(varchar, GETDATE(), 103) + ' ' + StartTime) >=
CONVERT(datetime, CONVERT(varchar, GETDATE(), 103) + ' ' + '8:00AM'))
AND
(CONVERT(datetime, CONVERT(varchar, GETDATE(), 103) + ' ' + EndTime) <=
CONVERT(datetime, CONVERT(varchar, GETDATE(), 103) + ' ' + '9:00AM'))
select *
from TimeList1
where StartTime >= '8:00AM'
and EndTime <= '9:00AM'
Less than or equal, not greater than or equal.
Though really, that doesn't work like you expect when your columns are of type varchar. Use a time or datetime type.
The first two paragraphs don't explain a thing as far as I can see. The last paragraph contains a flimsy explanation of the problem. – Jonathan Leffler
In the original post, before you edited it, the OP had as his select statement,
select *
from TimeList1
where StartTime >= '8:00AM'
and EndTime >= '9:00AM'
I was responding to that.
My response may be "flimsy", but I wanted to address the obvious problem and get the guy moving forward.

SQL generating a set of dates

I am trying to find a way to have a SELECT statement return the set of dates between 2 input dates with a given interval. I would like to be able to easily change the time frame and interval that would be returned, so hard coding something with a series of SELECT ... UNIONs would not be ideal.
For example: I want all the dates at 5 second intervals for the last 60 seconds.
Expected:
times
---------------------
2009-02-05 08:00:00
2009-02-05 08:00:05
2009-02-05 08:00:10
2009-02-05 08:00:15
2009-02-05 08:00:20
...
2009-02-05 08:00:55
Edit:
generate_series(...) can be used in place of a table in the SELECT and simulates a table with a series of numbers in it with a given start value, end value and optionally a step. From there it can be CAST to the type I need for time functions and manipulated during the SELECT.
Thanks Quassnoi.
SELECT CAST (s || ' seconds' AS INTERVAL) + TIMESTAMP 'now'
FROM generate_series(0, -60, -5) s