SQL DATEDIFF of am pm - sql

i want to calculate the time difference between two times, but my problem is maybe the second time will be after midnight, and the first before it like:
time 1 = '2015-08-02 09:30 PM'
time 2 = '2015-08-03 02:30 AM'
so in this case the difference between them will be negative,
i try to multiply the value returned by -1 to convert it to positive value, but other data will be wrong..
my code is:
DECLARE #StartDate datetime = '2015-08-02';
DECLARE #EndDate datetime = '2015-08-02';
DECLARE #EmpID nvarchar(6) = '12345';
SELECT
SUM(CASE WHEN(DATEDIFF(minute, a.[Time], #StartDate)) < 0
then DATEDIFF(minute, a.[Time], #StartDate) * -1
ELSE DATEDIFF(minute, a.[Time], #StartDate) END
)
FROM
Attendance a
WHERE
(EmpID = #EmpID OR #EmpID IS NULL)
AND a.[date] <= #EndDate
GROUP BY EmpID
so how can i solve it?

I don't see anything wrong in your code. But i would use this syntax instead:
SUM(ABS(DATEDIFF(minute, a.[Time], #StartDate)))

I think that the following:
CASE WHEN a.[Time] > #StartDate
THEN DATEDIFF(minute,#StartDate,a.[Time])
ELSE DATEDIFF(minute,a.[Time],#StartDate)
END
Should do it and will always give a positive value.
select datediff(minute, '2015-08-02 09:30 PM' ,'2015-08-03 02:30 AM')
Returns 300, which is correct (5 hours, 5 * 60 =300)

Related

How can I find out if getDate() is between 2 time(7) timestamps?

I have an application that sends alerts if the temperature exceeds limits, but I only want to send alerts if it happens at certain times of the day.  I'm using time(7) datatype to store those times.  I need it to be flexible enough to cross midnight, so I could have the following times:
time_on  time_off
08:00:00  17:00:00
00:00:00  12:00:00
21:00:00  09:00:00
How can I figure out if CONVERT(time(7), getdate()) is between any of those combinations?
You can do:
select a.*
from alerttimes a
where (time_on <= time_off and cast(getdate() as time) >= time_on and cast(getdate() as time) < time_off) or
(time_on > time_off and cast(getdate() as time) <= time_on and cast(getdate() as time) >= time_off);
This handles the issue with your table, which is that some period include midnight.
You can add TIME to a datetime value. Here we truncate the current GetDate() to midnight via Declare #D datetime = convert(date,GetDate())
Declare #YourTable table (time_on time,time_off time)
Insert Into #YourTable values
('08:00:00','17:00:00'),
('00:00:00','12:00:00'),
('21:00:00','09:00:00'),
('00:00:00','12:00:00'), -- Added for illustration
('12:00:00','00:00:00') -- Added for illustration
Declare #D datetime = convert(date,GetDate())
Select *
From #YourTable
Where GetDate() >= #D+convert(datetime,time_on)
and GetDate() <= #D+convert(datetime,time_off)+case when time_off<=time_on then 1 else 0 end
Returns
time_on time_off
12:00:00.0000000 00:00:00.0000000
My current Datetime was 2017-04-02 18:33:53.803 which did not satisfy any of the original criteria, so I added two records for illustration
Or, if you don't want to declare #D
Select *
From #YourTable
Where GetDate() >= convert(datetime,convert(date,GetDate()))+convert(datetime,time_on)
and GetDate() <= convert(datetime,convert(date,GetDate()))+convert(datetime,time_off)+case when time_off<=time_on then 1 else 0 end

SQL Server Date comparison throws error

Please help on this, how independent query works but comparison is failing for below code,I am trying to compare only dates not time so tried the query like this.
SELECT CAST(getdate() AS DATE)---'2/9/2017 12:00:00 AM'
SELECT CAST('2017/01/15' AS DATE)----'1/15/2017 12:00:00 AM'
SELECT CAST(getdate() AS DATE) > CAST('2017/01/15' AS DATE); -- Error SQLSTATE 42000
You need to put this condition into context. For instance like this
SELECT case when CAST(getdate() AS DATE) > CAST('2017/01/15' AS DATE)
then 1
else 0
end
Try something like this:
DECLARE #nowDate DATE
SELECT #nowDate = CAST(getdate() AS DATE)
DECLARE #otherDate DATE
SELECT #otherDate = CAST('2017/01/15' AS DATE)
SELECT DATEDIFF(DAY, #nowDate, #otherDate)
SELECT CAST(getdate() AS DATE)---'2/9/2017 12:00:00 AM'
SELECT CAST('2017/01/15' AS DATE)----'1/15/2017 12:00:00 AM'
SELECT IIF(CAST(getdate() AS DATE) > CAST('2017/01/15' AS DATE),1,0); --good, you must use iif (or case when ) for predicates
You cannot compare in SELECT, you can use below code to determinate if date is greater or not than current date, or it is today.
DECLARE #DATE NVARCHAR(20) = '2017/01/15'
IF (CAST(getdate() AS DATE) > CAST(#DATE AS DATE))
PRINT 'Selected date is in past'
ELSE IF (CAST(getdate() AS DATE) = CAST(#DATE AS DATE))
PRINT 'Selected date is today'
ELSE
PRINT 'Selected date is in future'
You can try DATEDIFF() to find out difference between 2 dates.
select DATEDIFF( DAY,(CAST('2017/01/15' AS DATE)) ,(CAST(getdate() AS DATE)))

Query to select a count group by time period

I have a typical log table with many details and a datetime of when the record was created.
I'm trying to analyse how many times does an event occurs per a time period (each 30 mins). I need to be able to analyze for a period bigger than one day. Basically, my desired output would be something like:
Period | Total
Day 1 00:00 - 00:30 | 23
Day 1 00:30 - 01:00 | 0
Day 1 01:00 - 01:30 | 534
...
Day 2 23:00 - 23:30 | 23
I'm flexible on the date column layout - I just need to be "readable"!
Here's my try but it's not working very well
declare #startdatetime datetime = '2016-02-03 00:00:00'
declare #enddatetime datetime = '2016-02-19 23:59:59'
declare #apiserviceid int = 21
select DATEPART(MINUTE, usr.STARTDATETIME) % 30, COUNT(*)
from TABLE 1 usr
where usr.APIREQUESTID = #apiserviceid
and usr.STARTDATETIME >= #startdatetime and usr.STARTDATETIME <= #enddatetime
group by
(DATEPART(MINUTE, usr.STARTDATETIME) % 30)
order by 1;
Thanks :)
DATEPART(MINUTE,...) are just the minutes within one hour, not the minutes within one day. Consider the hours as well
select (60 * DATEPART(HOUR, usr.STARTDATETIME) +
DATEPART(MINUTE, usr.STARTDATETIME)) % 30, COUNT(*)
...
I would recommend using a recursive CTE to generate all of your 30 min time segments and then JOIN on your table to find the occurrences.
DECLARE #startdate DATETIME = '2016-02-23'--your_starting_date
DECLARE #enddate DATETIME = '2016-03-01' --your_ending_date
;WITH cte AS (
SELECT
#startdate AS start_time
, DATEADD(MINUTE, 30, #startdate) AS end_time
UNION ALL
SELECT DATEADD(MINUTE, 30, start_time) AS start_time
, DATEADD(MINUTE, 30, end_time) AS end_TIME
FROM cte
WHERE end_time <= #enddate
)
SELECT *
INTO #time_table
FROM CTE
OPTION (MAXRECURSION 32727)
GO
SELECT
start_time
, end_time
, SUM(CASE WHEN your_time_column BETWEEN start_time AND end_time THEN 1 ELSE 0 END) AS total_count
FROM #time_table
INNER JOIN your_table --left join if you want all time slots with 0 occurrences
ON your_time_column BETWEEN start_time AND end_time
GROUP BY
start_time
, end_time
This will group by on the hour (not 30 min)
declare #startdatetime datetime = '2016-02-03 00:00:00'
declare #enddatetime datetime = '2016-02-19 23:59:59'
declare #apiserviceid int = 21
select min(usr.STARTDATETIME), max(usr.STARTDATETIME), count(0)
from TABLE 1 usr
where usr.APIREQUESTID = #apiserviceid
and usr.STARTDATETIME >= #startdatetime and usr.STARTDATETIME <= #enddatetime
group by convert(char(13),usr.STARTDATETIME,121)
order by 1;
select cast(year(usr.STARTDATETIME) as varchar)+''
+cast(month(usr.STARTDATETIME) as varchar)+
'-'+cast(day(usr.STARTDATETIME) as varchar)+' '+CAST(DATEPART(HOUR, usr.STARTDATETIME) AS VARCHAR)+':'+
CASE WHEN DATEPART(MINUTE, usr.STARTDATETIME)>30 THEN '31 - '+
CAST((DATEPART(HOUR, usr.STARTDATETIME)+1) AS VARCHAR) +':00' ELSE '00 -
'+CAST(DATEPART(HOUR, usr.STARTDATETIME) AS VARCHAR)+':30' END , COUNT(*)
from TABLE 1 usr
where usr.APIREQUESTID = #apiserviceid
and usr.STARTDATETIME >= #startdatetime and usr.STARTDATETIME <= #enddatetime
group by
cast(year(usr.STARTDATETIME) as varchar)+'-'+
cast(month(usr.STARTDATETIME) as varchar)+'-'+cast(day(usr.STARTDATETIME) as
varchar)+' '+CAST(DATEPART(HOUR, usr.STARTDATETIME) AS VARCHAR)+':'+
CASE WHEN DATEPART(MINUTE, usr.STARTDATETIME)>30 THEN '31 - '+
CAST((DATEPART(HOUR, usr.STARTDATETIME)+1) AS VARCHAR) +':00' ELSE '00 -
'+CAST(DATEPART(HOUR, usr.STARTDATETIME) AS VARCHAR)+':30' END
order by 1;

Having issues with dates in SQL

I'm writing a report that needs to collect data each day, between 0900hs and 1700hs.
I thought it would be fine as follows:
cast(convert(char(8),t.trxtime,112)as time)
between CONVERT(VARCHAR(5),getdate(),108) >= '09:00'
and CONVERT(VARCHAR(5),getdate(),108) < '17:00'
....BUT no cigar.
Thank you!!!
Hmmm, you could just use datepart():
where datepart(hour, t.trxtime) between 9 and 16 and
cast(t.trxtime as date) = cast(getdate() as date)
I'm not sure if the date comparison is actually necessary.
You could do something like this (assuming you mean actually for the current date, and not for every date in a range:
declare #startDate datetime
declare #endDate datetime
select #startDate = '2014-11-03 09:00:00',
#endDate = '2014-11-03 17:00:00'
select *
from table
where myDate between #startDate and #endDate
if you did mean between 0900 and 1700 for each day, you could do:
declare #startDate datetime
declare #endDate datetime
select #startDate = '2014-10-03',
#endDate = '2014-11-03' -- note i'm still limiting it to a range of ~1 month
select *
from table
where myDate between #startDate and #endDate
and datepart(hour, myDate) between 9 and 17

Realy year datediff (no year less)

I need to calculate the year diferences between two dates.
Tried using DATEDIFF but that only do the less of the dates, for example:
Date 1: 07/03/2011
Date 2: 07/02/2012
(Date format MM/DD/YYYY)
Then: DATEDIFF([yyyy], '07/03/2011', '07/02/2012') = 1
But the real diferences are 0 year.
This should work
declare #date1 datetime
declare #date2 datetime
select #date1 = '20110703', #date2 = '20120703'
select case
when dateadd(yy, DATEDIFF(yy, #date1, #date2), #date1) > #date2
then DATEDIFF(yy, #date1, #date2) -1
else DATEDIFF(yy, #date1, #date2) end
A fuller test case showing many edge conditions
create table dates(id int identity, date1 datetime, date2 datetime)
insert dates select '20110703', '20120703'
insert dates select '20110703', '20120702'
insert dates select '20110702', '20120703'
insert dates select '20110228', '20120228'
insert dates select '20120229', '20130228'
insert dates select '20120229', '20130301'
insert dates select '20110301', '20120229'
insert dates select '20120229', '20160301'
insert dates select '20120229', '20160229'
insert dates select '20101231', '20110101'
insert dates select '20100101', '20111231'
select date1, date2,
case
when dateadd(yy, DATEDIFF(yy, date1, date2), date1) > date2
then DATEDIFF(yy, date1, date2) -1
else DATEDIFF(yy, date1, date2) end
from dates
order by id
Since noone had a correct solution i post mine even though noone will ever notice.
declare #d1 datetime
declare #d2 datetime
set #d1 = '1968-02-29'
set #d2 = '2011-02-28'
select datediff(year, #d1, #d2)-
case when month(#d1)*32 + day(#d1) > month(#d2) * 32 + day(#d2) then 1 else 0 end
--case when month(#d2)*32 + day(#d1) > month(#d2) * 32 + day(#d2) then 1 else 0 end
This method is basically the same as the next method, difference is that it is done with numbers to avoid the casting, which i was told was slower.
select datediff(year, #d1, #d2)-
case when convert(char(5),#d1, 1) > convert(char(5),#d2, 1) then 1 else 0 end
SQL Server just does a year diff if you specify [yyyy].
For DATEDIFF([yyyy], '07/03/2011', '12/31/2011') it will return zero.
For DATEDIFF([yyyy], '07/03/2011', '01/01/2012') it will return 1.
In your case you should count the days if you are looking for 365 or 366 days:
DATEDIFF([dd], '07/03/2011', '07/02/2012') / 366
Yeah, DATEDIFF works that way with all dateparts, so I guess you should calculate the difference in days and then divide by 365 (this, if you don't care about the time of day). Si, try this:
DECLARE #StartDate DATETIME, #EndDate DATETIME
SET #StarDate= '20110307'
SET #EndDate = '20120207'
SELECT DATEDIFF(DAY,#StartDate, #EndDate)/365
After reviewing the question and answers a bit more, all I've got to offer is some linkage: http://msdn.microsoft.com/en-us/library/ms189794.aspx.