Using between on a datepart with both hour and minute - sql-server

I have a time field called Epoch that I know how to pull data from 6 to 8 AM out of. I do not know how to do that for 6:30 to 8:30, since datepart is hour or minute not both. Here is the code I have thus far.
select tmc_code, avg(speed) as AVGS
from [dbo].[CEAR_FULL_NONULL_CARS_3_12]
where epoch between (datepart(hour, epoch) = 6 and datepart(minute, epoch) = 30) and (datepart(hour, epoch) = 8 and datepart(minute, epoch) = 25)
group by TMC_Code order by tmc_code

Assuming Epoch is a datetime, perhaps convert to a TIME
Declare #YourTable table (epoch datetime)
Insert into #YourTable values
('2020-01-22 07:22:18')
,('2020-01-22 10:45:00')
Select *
From #YourTable
Where convert(time,epoch) between '06:30' and '08:30'
Returns
epoch
2020-01-22 07:22:18.000

Related

Convert a time calculation to time in HH:MM

I am looking to create a calculation in SQL Server that will display the time difference in HH_MM from a time column.
For example, the difference in hours and minutes between
5:45 PM - 3:30 PM = 2:15 (desired output)
The closest I have been able to get is this:
CONVERT(TIME,cals_END_time - cals_START_time) = 02:15:00.0000000
How do I go about 'trimming' it down to 2:15?
Assuming the columns are datetime, use the format function to format the time value:
select format(cast(cals_end_time - cals_start_time as time), N'h\:mm')
from (values
(cast('2022-07-07 15:30:00' as datetime), cast('2022-07-07 17:45:00' as datetime))
) as tests(cals_start_time, cals_end_time)
DB<>Fiddle
If you want to add/subtract dates/datetimes you need to use the relevant functions to do so as follows:
select *, convert(varchar(5), dateadd(minute, datediff(minute, [TimeOut], TimeIn), convert(time, '00:00'))) TimeDifference
-- , CONVERT(TIME, [TimeOut], TimeIn) -- gives an error anyway?
from (
values
(convert(time, '05:45 PM'), convert(time, '03:30 PM'))
) x (TimeIn, [TimeOut]);
Returns:
TimeIn
TimeOut
TimeDifference
17:45:00.0000000
15:30:00.0000000
02:15

Select records created in a 24 hour time-frame

I'm trying to query our database to find all records that were created between 6am yesterday and 6am today. This will be run in a report at any point during the day so set times/dates are useless.
I have this so far:-
SELECT * FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime BETWEEN DATEADD(DAY, -1, GetDate())
AND DATEADD(Day, 1, GetDate())
But obviously this only works for 24 hours ago from right now until right now. I can't figure out how to apply a time as well as date.
Every example I find online seems slightly different and uses set dates/times ie, >= 20/02/2015 06:00:00.
I normally use Oracle SQL which would simply work using this:-
ptt.mod_date_time >= TRUNC (SYSDATE - 1) - 2 / 24
AND ptt.mod_date_time <= TRUNC (SYSDATE - 1) + 22 / 24
This would return results from 10pm to 10pm but the format appears totally different in SQL Server.
You can get the datetime values you are after by doing the following:
SELECT DATEADD(HOUR,6,CONVERT(DATETIME, CONVERT(DATE ,GETDATE()))) Today6AM,
DATEADD(HOUR,-18,CONVERT(DATETIME, CONVERT(DATE ,GETDATE()))) Yesterday6AM
By doing this: CONVERT(DATE ,GETDATE()) you are stripping off the time portion of today's date. Converting it back to datetime gives you midnight for today.
The query adds 6 hours to midnight of the current day for 6am today and subtracts 18 hours from midnight of the current day to give you 6am on the previous day.
Output:
Today6AM Yesterday6AM
================================================
2015-02-20 06:00:00.000 2015-02-19 06:00:00.000
So adding that to your query:
SELECT *
FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime
BETWEEN DATEADD(HOUR,-18,CONVERT(DATETIME, CONVERT(DATE ,GETDATE())))
AND DATEADD(HOUR,6,CONVERT(DATETIME, CONVERT(DATE ,GETDATE())))
DECLARE #StartTimestamp datetime
DECLARE #EndTimestamp datetime
DECLARE #HourPartOfSearchRange nvarchar(6)
SET #HourPartOfSearchRange = ' 06:30'
SET #StartTimestamp =
CAST((CONVERT(varchar(11), DATEADD(DAY,-1,#CurrentUTCDateTime), 106) + #HourPartOfSearchRange) AS datetime)
SET #EndTimestamp =
CAST((CONVERT(varchar(11), #CurrentUTCDateTime, 106) + #HourPartOfSearchRange) AS datetime)
SELECT * FROM dbo.Test Where Timestamp Between #StartTimestamp AND #EndTimestamp
today 6am is
dateadd(hour,6,cast(cast(getdate() as date) as datetime))
cast(getdate() as date) truncates the timepart, cast it back as datetime because dateadd won't add hours otherwise and add 6hours
One solution would be like so:
select *
from DaySummaryDetail DSD
where DSD.FromDateTime between cast(cast(cast(getdate()-1 as date) as varchar(30)) + ' 06:00:00.000' as datetime)
and cast(cast(cast(getdate() as date) as varchar(30)) + ' 06:00:00.000' as datetime)
This should help ...
SELECT DATEADD( hour, 6, CAST(CAST(GETDATE(), AS Date) AS DateTime) ) AS 'Today#6am'
SELECT DATEADD( hour, 6, CAST(CAST(GETDATE()-1, AS Date) AS DateTime) ) AS 'Yesterday#6am'
In SQL Server 2012 you can use SMALLDATETIMEFROMPARTS to construct a datetime value that is today at 6am like this:
SMALLDATETIMEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), DAY(GETDATE()), 6, 0)
Output: 2015-02-20 06:00:00
then you can use the above expression in place of GETDATE() in the WHERE clause:
DECLARE #TodayAt6AM DATETIME = SMALLDATETIMEFROMPARTS(YEAR(GETDATE()),
MONTH(GETDATE()),
DAY(GETDATE()),
6,
0)
SELECT *
FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime BETWEEN DATEADD(DAY, -1, #TodayAt6AM) AND
DATEADD(Day, 1, #TodayAt6AM)

SQL Server DateTime format from automatic export script

When using the mssql script generation with data the datetime is exported with a cast:
CAST(0x00009E0E0095524F AS DateTime)
Does anyone know what format is used ?
The date in the example is shown as 2010-10-13 09:03:39.783.
Upper 4 bytes = days from 01 Jan 1900, lower 4 = time of day
It's the internal storage of datetime which is 8 bytes as two 4 byte integers, one with whole days, the other as fraction of day.
DECLARE #inttop bigint, #TheValue bigint
SET #inttop = POWER(CAST(2 AS bigint), 32)
SET #TheValue = CAST(0x00009E0E0095524F AS bigint)
SELECT
--days since 01 Jan 1900
#TheValue / #inttop,
--fractional time of day
CAST(#TheValue % #inttop AS float) / #inttop
--and confirm it
SELECT
DATEADD(DAY, #TheValue / #inttop, 0),
CAST(CAST((#TheValue % #inttop) AS float) / #inttop AS datetime)

How to calculate difference in hours (decimal) between two dates in SQL Server?

I have to calculate the difference in hours (decimal type) between two dates in SQL Server 2008.
I couldn't find any useful technique to convert datetime to decimal with 'CONVERT' on MSDN.
Can anybody help me with that?
UPDATE:
To be clear, I need the fractional part as well (thus decimal type). So from 9:00 to 10:30 it should return me 1.5.
DATEDIFF(hour, start_date, end_date) will give you the number of hour boundaries crossed between start_date and end_date.
If you need the number of fractional hours, you can use DATEDIFF at a higher resolution and divide the result:
DATEDIFF(second, start_date, end_date) / 3600.0
The documentation for DATEDIFF is available on MSDN:
http://msdn.microsoft.com/en-us/library/ms189794%28SQL.105%29.aspx
Just subtract the two datetime values and multiply by 24:
Select Cast((#DateTime2 - #DateTime1) as Float) * 24.0
a test script might be:
Declare #Dt1 dateTime Set #Dt1 = '12 Jan 2009 11:34:12'
Declare #Dt2 dateTime Set #Dt2 = getdate()
Select Cast((#Dt2 - #Dt1) as Float) * 24.0
This works because all datetimes are stored internally as a pair of integers, the first integer is the number of days since 1 Jan 1900, and the second integer (representing the time) is the number of (1) ticks since Midnight. (For SmallDatetimes the time portion integer is the number of minutes since midnight). Any arithmetic done on the values uses the time portion as a fraction of a day. 6am = 0.25, noon = 0.5, etc... See MSDN link here for more details.
So Cast((#Dt2 - #Dt1) as Float) gives you total days between two datetimes. Multiply by 24 to convert to hours. If you need total minutes, Multiple by Minutes per day (24 * 60 = 1440) instead of 24...
NOTE 1: This is not the same as a dotNet or javaScript tick - this tick is about 3.33 milliseconds.
DATEDIFF but note it returns an integer so if you need fractions of hours use something like this:-
CAST(DATEDIFF(ss, startDate, endDate) AS decimal(precision, scale)) / 3600
Using Postgres I had issues with DATEDIFF, but had success with this:
DATE_PART('day',(delivery_time)::timestamp - (placed_time)::timestamp) * 24 +
DATE_PART('hour',(delivery_time)::timestamp - (placed_time)::timestamp) +
DATE_PART('minute',(delivery_time)::timestamp - (placed_time)::timestamp) / 60
which gave me an output like "14.3"
You are probably looking for the DATEDIFF function.
DATEDIFF ( datepart , startdate , enddate )
Where you code might look like this:
DATEDIFF ( hh , startdate , enddate )
DATEDIFF(minute,startdate,enddate)/60.0)
Or use this for 2 decimal places:
CAST(DATEDIFF(minute,startdate,enddate)/60.0 as decimal(18,2))
Declare #date1 datetime
Declare #date2 datetime
Set #date1 = '11/20/2009 11:00:00 AM'
Set #date2 = '11/20/2009 12:00:00 PM'
Select Cast(DateDiff(hh, #date1, #date2) as decimal(3,2)) as HoursApart
Result = 1.00
SELECT DATEDIFF(hh, firstDate, secondDate)
FROM tableName
WHERE ...

TS SQL - group by minute

I have a table with timestamps. What is the proper query to get the records counts for each minute for the last hour.
I.e. if now is 2:25, I want to know how many record were between 1:25 and 1:26, 1:26 and 1:27, and so on, so I have 60 results.
This will return a count of results for each minute (where you have records) in the last hour
SELECT DATEPART(n, time_stamp) AS minute, COUNT(*) as results
FROM table_name
WHERE time_stamp > DATEADD(hh, -1, GETDATE())
GROUP BY DATEPART(n, time_stamp)
This may return less than 60 results, depending on the data. If you have to have 60 results, the query is slightly different. This uses a Common Table Expression to generate a list of 60 numbers and a correlated sub-query to get the results for each minute:
WITH numbers ( num ) AS (
SELECT 1 UNION ALL
SELECT 1 + num FROM numbers WHERE num < 60 )
SELECT num AS minute,
(SELECT COUNT(*) AS results
FROM table_name
WHERE DATEPART(n, time_stamp) = num
AND time_stamp > DATEADD(hh, -1, GETDATE())
FROM numbers
To see the results, replace DATEADD(hh, -1, GETDATE()) with DATEADD(mi, -15, GETDATE()) and you'll get the results for the last 15 minutes and 0 for other minutes.
This is an alternative I have found useful for determining how many records are inserted or updated per minute. The nice thing about having your date format as a variable up front is that you can easily change it to analyze per hour instead. Hope this helps!
DECLARE #dateFormat as varchar(max) = 'yyyy-MM-dd HH:mm'
SELECT format(timeColumn, #dateFormat) AS minute, COUNT(*) as results
FROM yourTable
WHERE timeColumn > DATEADD(hh, -1, GETDATE())
GROUP BY format(timeColumn, #dateFormat)
ORDER BY 1
As you edited the question, I edit my answer. If I have understood you correctly, you want to look only at the past hour - that is, a timespan from one hour before the request is made to the current time. This is how I'd do it:
SELECT
COUNT(yourTimeStamp)
FROM yourTable
WHERE DATEADD('hh', -1, GetDate()) <= yourTimeStamp
AND yourTimeStamp < GetDate()
GROUP BY DATEPART('mm', yourTimeStamp)
I am not entirely sure that the syntax is exact. When coding in MSSQL, I would use the CURRENT_TIMESTAMP for the current time, MINUTE instead of DATEPART etc, but you get the idea for the solution.
DATEPART is what you're looking for:
declare #times table
(
someTime datetime
)
INSERT INTO #Times (sometime) values ('jan 12 2008 12:23')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:34')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:35')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:25')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:02')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:09')
INSERT INTO #Times (sometime) values ('jan 12 2008 12:35')
select DATEPART(mi,sometime) AS Minute, count(*) AS NumOccurances
from #Times
WHERE SomeTime BETWEEN #Lower AND #Upper
GROUP BY DATEPART(mi, sometime)
order by NumOccurances DESC
Result:
Minute NumOccurances
35 2
2 1
9 1
23 1
25 1
34 1
If you want to group results by minute, then you can use a formatted string. This will group by number of minutes since 1/1/1900 not minute within day.
WITH formatted AS (
SELECT FORMAT(<your_datetime_column>, 'yyyy-MM-dd HH:mm') AS minute_text
FROM <your_table>
)
SELECT minute_text, COUNT(*) AS number_of_rows
FROM formatted
GROUP BY minute_text
ORDER BY 1 DESC
Here's my fixed up version of Robin's answer. I made it output the errors in the correct order and output the time as well instead of just the number which isn't super useful if you're charting this out.
WITH numbers ( num ) AS (
SELECT 1 UNION ALL
SELECT 1 + num FROM numbers WHERE num < 60 )
SELECT (SELECT DATEADD(n, -num, GETDATE())) AS TimeStamp,
(SELECT COUNT(*) AS results
FROM ErrorLogs
WHERE DATEPART(n, TimeStamp) = DATEPART(n, DATEADD(n, -num, GETDATE()))
AND TimeStamp > DATEADD(hh, -1, GETDATE())) as Count
FROM numbers
SELECT COUNT (TS) from TABLE where TABLE.TS BETWEEN(starttime, endtime)

Resources