How to change both date and time in a datetime in SQL - sql

I try to set the time and date in my query based one the following conditions:
if time in MyDate < 9:00 then set the time to 9:00
If time in 9:00 < MyDate < 15:00 then set the time to 16:00
If time is MyDate > 15:00 then set the time to 9:00 and the day to day+1
I have the two first conditions in place and works fine, but cannot combine changes in both time and date. How can I do that?
The code below works fine for the two first conditions!
Case When cast(MyDate as TIME) < '09:00:00' Then DATEADD(Hour, 9, CAST(CAST(PayoutDtApplication As Date) As Datetime))
Case When cast(MyDate as TIME) < '09:00:00' Then DATEADD(Hour, 9, CAST(CAST(PayoutDtApplication As Date) As Datetime))
THanks

This is a guess, based on the following comment:
this numbers can varries based on the data I get, just wanted to say I need to set the time to 9:00 and day+1 for all dates I get. I have different dates.
I'm guessing that regardless of the time, the OP wants to change the value to the following date at 09:00:00.
If so, one way to achieve it would be:
SELECT DATEADD(HOUR, 33, CONVERT(date,YourDateColumn)) AS NewDate
FROM YourTable;
Again, this is guesswork. If the OP elaborates, I'll be happy to expand my answer, or remove it if it's irrelevant.
Edit: Based on the OP's new logic from their edit:
CREATE TABLE #Sample (YourDate datetime2(0));
INSERT INTO #Sample
VALUES ('2018-05-09T08:57:00'),
('2018-05-09T14:26:37'),
('2018-05-09T19:24:01');
GO
SELECT YourDate,
CASE WHEN CONVERT(time, YourDate) < '09:00:00' THEN DATEADD(HOUR,9,CONVERT(datetime2(0),CONVERT(date,YourDate)))
WHEN CONVERT(time, YourDate) > '15:00:00' THEN DATEADD(HOUR,33,CONVERT(datetime2(0),CONVERT(date,YourDate)))
ELSE DATEADD(HOUR,15,CONVERT(datetime2(0),CONVERT(date,YourDate))) END AS NewDate
FROM #Sample;
GO
DROP TABLE #Sample;
The double CONVERT (CONVERT(datetime2(0),CONVERT(date...) is because the data type date isn't compatible with DATEADD(HOUR.... I have used datetime2 as this should be used over datetime now.

Related

Auto Update Date for Given range in SQL

I have a SQL query by which I have to extract data from the server but every time I have to change the date range
where date(usf.created_date) BETWEEN '2022-04-01 00:00:00' and '2022-04-30 23:59:59'
but I want to get this range auto-update from today 30 days back.
I have tried the casting method Cast(GETDATE() as smalldatetime) but it shows an error in the same.
Assuming based on GETDATE() that this is SQL Server, you either want:
-- get everything going back exactly 30 days from this moment
WHERE usf.created_date >= DATEADD(DAY, -30, GETDATE());
Or:
-- get everything going back 30 days from this morning at midnight
WHERE usf.created_date >= DATEADD(DAY, -30, CONVERT(date, GETDATE()));

Rounding DateTime in SQL

I have DateTime data in a MS SQL database with the following format:
2020-05-07 22:35:00
I am trying to create a query that only captures data from the last 24 hours of operations. However, our operations KPIs are measured from 6AM-6AM. I would like to round the date based on time. Anything before 6AM will be counted as the day before.
2020-05-07 05:45:00 -> 2020-05-06 (Before 6AM)
2020-05-07 06:30:00 -> 2020-05-07 (After 6AM)
So far I have been successful in pulling the previous days activity, but am struggling to shift the timeframe to round down anything before 6AM
SELECT
end_date
FROM data sint
WHERE sint.end_date >= dateadd(day,datediff(day,1,GETDATE()),0)
AND sint.end_date < dateadd(day,datediff(day,0,GETDATE()),0)
You can add six hours to the current date (without the time) for the comparison:
where int.end_date < dateadd(hour, 6, convert(datetime, convert(date, getdate()))) and
int.end_date >= dateadd(hour, 6 - 24, convert(datetime, convert(date, getdate())))
Note that the conversion to date removes the time component.
first get the time part. Compare the time part with 6AM and run your expression.
In below code the time part is compared with the date '1900-01-01 06:00:00' which is 6AM in default date format.
select
case when cast(date as time(0)) < '1900-01-01 06:00:00'
then cast(date - 1 as date)
else cast(date as date)
end as newdate
from temp_date;
I would do the same as Gordon only the opposite side.
I would subtract 6 hours from end_date and then compare.
where convert(date, dateadd(hour, -6, int.end_date)) = convert(date, getdate())
Though this method might not work well if you're actually using getdate(). It will return nothing if it is ran between midnight and 6 am (unless you have future dates).

How to show Current Date as Current Date ending at 3:00:00AM in SQL

I have a task that I need to show the current date time as ending at 3:00:00 AM at current date. For example, GETDATE() returns the current date time when executes. I need to show it as 9/5/2019 3:00:00 AM instead. Below is my code:
DECLARE #END_SHIFT AS DATETIME
SET #END_SHIFT = '06:00:00 AM'
SELECT
NUMBER_ID,
GETDATE() AS CURRENT_DT,
GETDATE() - #END_SHIFT AS END_SHIFT_DATE
FROM table
My issue when running this is it does not return as ending at 3:00:00AM. Please let me know your direction.
Thanks,
H
A bit of an odd request for sure but you could simply use DATEADD.
SELECT dateadd(hour, 3, convert(datetime, convert(date, getdate())))
If you really need a "hard" time, one option is to use format()
Example
Select format(GetDate(),'yyyy-MM-dd 03:00')
Returns
2019-09-05 03:00

SQL Server - Check if given date+time is between two datetime variables by exact date+time

I have two datetime columns in a DB table: #Start and #End.
Both columns contain the date and time, for example:
#Start: 2018-10-01 19:00:00
#End: 2018-10-10 23:59:00
I want to know if the current date is exactly between both datetimes considering the dates and the times.
So, 2018-10-08 16:37 and 2018-10-10 23:59:00 would match this range
and 2018-10-11 00:00:00 would not.
(In this case this date is one minute later than the End date, so it is not between my datetime range).
SELECT Id FROM Table1 WHERE GETDATE() BETWEEN Start AND End
I don't use GETDATE() in real code, I use an argument. The problem is that current date argument may contain seconds and milliseconds like 23:59:59.123. My code treats such date as not conforming given range. But I don't care about s/ms.
Is there a workaround?
Update:
The precision I want to achieve is in minutes. So I do not even need to take in account the seconds nor the milliseconds. The date time format I would be working on would be 'yyyy-MM-dd hh-mm' but I do not know how to use the BETWEEN clause converting the Start and End to the shown format so I can compare the dates.
You would seem to want this logic:
WHERE GETDATE() >= Start
AND GETDATE() < DATEADD(minute, 1, End)
Assuming that the time part of End is 23:59:00 it covers all possible values between 23:59:00 and 23:59:59.999...999.
SELECT Id FROM Table1 WHERE GETDATE() BETWEEN '2018-10-01 19:00:00' AND '2018-10-10 23:59:00'
TRY
SELECT Id FROM Table1 WHERE
CONVERT(varchar(16),GETDATE(),121) BETWEEN
CONVERT(varchar(16),[Start], 121)
AND
CONVERT(varchar(16),[END],121);
Example of rounding without strings
DECLARE #GetDateMinutes as datetime2;
DECLARE #X as datetime2 = getdate();
--round to minutes, could be made into a function
SET #GetDateMinutes = dateadd(minute,datepart(minute,#x),dateadd(hour, datepart(hour,#x),cast(CAST(#x as date) as datetime2)))
select #x, #GetDateMinutes
Truncate the seconds using the technique described here to avoid all string conversions, then just do your comparison. Here's a fully contained example that uses cross apply and values to encapsulate the truncation logic for start and end:
-- truncate minutes from current date time
declare #currentDateTime datetime2(0) = DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), N'2018-10-01 23:58:32.912')), 0);
select #currentDateTime as CurrentDateTime
, a.*
from (values -- create a table of dummy values
(Convert(datetime2(3), N'2018-10-01 19:48:14.735'), Convert(datetime2(3), N'2018-10-10 02:00:00.000'))
, (Convert(datetime2(3), N'2018-10-01 22:43:19.532'), Convert(datetime2(3), N'2018-11-01 12:17:26.663'))
) as a (StartDateTime, EndDateTime)
cross apply (values(
-- truncate minutes from start date time
DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), a.StartDateTime)), 0)
-- truncate minutes from end date time
, DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), a.EndDateTime)), 0)
)) as b (StartDateTimeWithoutSeconds, EndDateTimeWithoutSeconds)
where #currentDateTime between b.StartDateTimeWithoutSeconds and b.EndDateTimeWithoutSeconds;
Your data appears to already have the s/ms truncated from start and end but figured I'd apply the same logic to all values involved just to be consistent. Here's the formula for stripping s/ms without all the "noise" from the example:
DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), <SomeDateTime>)), 0)

Update datetime values to same date but persist time

I'm in a situation where I would like to update the date of all the values in the table to have the same day but persist the time of each record.
So these three dates...
8/28/2012 14:00:00
8/28/2010 12:00:00
8/28/2008 10:00:00
Should be turned into...
8/28/2012 14:00:00
8/28/2012 12:00:00
8/28/2012 10:00:00
UPDATE MySpecialTable
SET DateField = {...?};
Edit: Regardless of the day the date is on (i.e. 8/28/2012, 1/1/2012, 4/1/2012, etc), I want to persist the time and mass update all the day/month/year to a specific value.
DECLARE #Target DATETIME;
SET #Target = '20120828';
-- if the date is supposed to be today rather than hard-coded or parameterized:
-- SET #Target = DATEADD(DAY, DATEDIFF(DAY, '19000101', CURRENT_TIMESTAMP), '19000101');
UPDATE dbo.MySpecialTable
SET DateField = DATEADD(DAY, DATEDIFF(DAY, DateField, #Target), DateField);
This will work if the target date is before or after the value in the column.
Also, if you only care about time, you should consider using the TIME data type (SQL 2008+). This will make it easy to apply any date you want to the data at query time, without having to actually perform any updates.
Here is one way, assuming you are using SQL Server 2008 or greater:
update MySpecialTable
set DateField = cast(CURRENT_TIMESTAMP as date) + (DateField - cast(DateField as date))
Try this (updated to have the same date):
DECLARE #myDate DATETIME
SET #myDate = '2012-08-28T00:00:00.000'
UPDATE [MySpecialTable]
SET [DateField] = DATEADD(Day, 0-DATEDIFF(Day, 0, [DateField]), [DateField]) + #myDate
DATEADD(Day, 0-DATEDIFF(Day, 0, [DateField]), [DateField]) gets the
timestamp and makes the date to the min value (1/1/1900)
Add the above to the desired date in the variable