I have columns Issue Date and Valid for:
Issue Date is the issue date of certification
Valid For (type INT) is the duration (number of years) of how long the certificate is valid for
I'm looking to get the exact expiry date.
Thanks
Screenshot of the table with sample data:
SQL Server has a simple function to add a number of time units to a date: DATEADD (datepart , number , date )
e.g. IF [Valid For] represents a number of days
select
[Issue Date]
, [Valid For]
, dateadd(day,[Valid For],[Issue Date]) as [Valid To Date]
from yourtable
The first parameter to that function is the "datepart" i.e. the appropriate time unit (such as: second, hour, day, week, month) that the column [Valid For] represents. The second parameter is treated as an integer (any decimal value is ignored).
So, choose the appropriate "datepart" that satisfies the intended meaning of the number held in [Valid For] in the dateadd() function. Refer to this page for details of the function.
dateadd(minute,convert(int,1440*[Valid For]),[Issue Date])
Related
I have a table with a [ID] ,[Timestamp] and [Message].
The [Timestamp] is in '2021-03-31 22:37:09.580' format and I want to calculate the time it takes for an advisor to answer the webchat conversion.
So far I have the following
I want to add the [Timestamp] to either of those messages and then calculate the difference between each one.
The current query returns the following
Can anyone help?
select
[message]
,NextMessage
from (
select id
, [message]
,lead([message]) over (order by id) as NextMessage
from bot.ConversationsResolved
) as t
where [message] = ('You''re being connected to the next available advisor.')
As some other users have rather 'helpfully' mentioned, you can find the syntax of the datediff function within Microsoft's documentation for SQL Server here:
https://learn.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-ver15
From this you can see that you need to specify a datepart which is the unit of time you want to measure as well as the start and end dates that you want to measure between. You use this in your select statement and it returns the value in a new column:
select StartDate
,EndDate
,datediff(day,StartDate,EndDate) as DayBoundariesCrossed
from YourTable
You will note that I have called that column DayBoundariesCrossed as that is what the datediff function actually returns. By specifying the day as our datepart we get the number of times you cross from one day into the next between those two dates. Had we specified year it would have been the number of year boundaries crossed.
This produces a potential pitfall called the fence post problem, where the value returned is likely one less than what you actually want; the datediff between today and tomorrow for example is just the one day boundary, though you may want to regard that as covering two days. In those instances you can just add 1 to the result of the datediff.
A slightly more challenging consequence of this requires that you always use the most appropriate datepart for your calculations, as the results of 'boundaries crossed' are not always desirable.
For example, this script:
select datediff(year,'2020-12-31 23:59:59','2021-01-01 00:00:00') as YearBoundaries
,datediff(month,'2020-12-31 23:59:59','2021-01-01 00:00:00') as MonthBoundaries
,datediff(day,'2020-12-31 23:59:59','2021-01-01 00:00:00') as DayBoundaries
,datediff(hour,'2020-12-31 23:59:59','2021-01-01 00:00:00') as HourBoundaries
,datediff(minute,'2020-12-31 23:59:59','2021-01-01 00:00:00') as MinuteBoundaries
,datediff(second,'2020-12-31 23:59:59','2021-01-01 00:00:00') as SecondBoundaries
will output the following, which likely isn't what was desired:
YearBoundaries
MonthBoundaries
DayBoundaries
HourBoundaries
MinuteBoundaries
SecondBoundaries
1
1
1
1
1
1
To combat this, you can specify the datepart at a level of detail higher than what you are actually after and divide down - e.g. datediff(month,StartDate,EndDate) / 12.0 to get year fractions - though even here there can be pitfalls that you will need to be mindful of.
I have table containing the columns:
1. ClockifyId,
2. StartTime EndTime of every Task
3. Date.
4. Duration
The image is attached below
My goal is to write query to calculate the total duration of every user(which is ClockifyId) of every date.
As One User can have multiple task in one day, I wanted to sum duration of all those task. In short,
I wanted to have total task duration of every user(which is clockifyid) of every date.
enter image description here
There are a couple of details missing here, but this should get you close enough.
The first thing you need to do is convert the StartTime and EndTime to datetime fields if they aren't already. Doing a DATEDIFF on them allows you to figure out per record what the difference in minutes is. You can change the unit of measure as needed.
Once you do that, you use the SUM() which is an aggregate function. This makes it necessary to use the GROUP BY. You then group by which ever fields, in this case the ClockifyId and the StartTime as a date. You have to do it as a date without the datetime or you will get multiple rows back for a single Clockify record in a day.
SELECT
ClockifyId
, SUM(DATEDIFF(mi, CAST(StartTime AS datetime), CAST(EndTime AS datetime))) AS DurationInMinutes
, CAST(StartTime AS date)
FROM TableName
GROUP BY
ClockifyId
, CAST(StartTime AS date)
It's worth noting that this assumes there is always a valid StartTime and EndTime. This will throw some errors if those fields have nulls.
I am trying to offset the time in the column based on the time zone. I am trying to use this:
SELECT
SERIAL_NUMBER,
CONVERT(datetime, TIME_FROM)
AT TIME ZONE ('US Eastern Standard Time')
FROM
tmp_TestZone
which returns what I need, however each row in my table has record with specific time zone which can be any time zone. What I have to do is to replace 'US Eastern Standard Time' with a nested query that will pull the correct time zone for particular serial number. Time zone is stored in the last column which is TIMEZONE_LU.TZ
My table looks like this:
,[IP_ADDRESS]
,[NAME]
,[GROUP_NAME]
,[DEVICE_TYPE]
,[LINE_NAME]
,[DATE_FROM]
,[TIME_FROM]
,[TIME_TO]
,[fw]
,[bw]
,[SITE_NAME]
,[TZ]
I tried to build the query like this:
SELECT
SERIAL_NUMBER,
CONVERT(datetime, TIME_FROM)
AT TIME ZONE (SELECT TZ
FROM tmp_TestZone) NEW_TIME
FROM
tmp_TestZone
But I'm getting an error:
Msg 512, Level 16, State 1, Line 2
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
How do I fix this?
The suggestion:
SELECT
SERIAL_NUMBER,
CONVERT(datetime, TIME_FROM)
AT TIME ZONE (SELECT TZ
FROM tmp_TestZone) NEW_TIME
FROM
tmp_TestZone
Would work however i just found that my timezones are not standardized.
I am going to try to use
SELECT SERIAL_NUMBER,
SWITCHOFFSET(TIME_FROM, '-05:00')
FROM tmp_TestZone2
Could you help me to replace '-05:00' from above code so ti reads values from UTC_offset column which are in exact format as '-05:00'
Thank you so much
Ok so here is the table:
SELECT [SERIAL_NUMBER]
,[IP_ADDRESS]
,[NAME]
,[GROUP_NAME]
,[DEVICE_TYPE]
,[LINE_NAME]
,[DATE_FROM]
,[TIME_FROM]
,[TIME_TO]
,[fw]
,[bw]
,[SITE_NAME]
,[TZ]
,[CC]
,[UTC_offset]
,[UTC_DST_offset]
FROM [VHA].[dbo].[tmp_TestZone2]
And here is the data of that table:
I have the columns TIME_FROM and TIME_TO that needs to be offset for UTC_Offset values.
So for the instance in the picture TIME_FROM (10:10:00) and TIME_TO (11:00:00) should be offset for -7:00 and so on for every row the TIME_FROM and TIME_TO should be offset for what ever value is in column UTC_Offset.
Try like this
SELECT
SERIAL_NUMBER,
CONVERT(datetime, TIME_FROM)
AT TIME ZONE temp.tz
FROM
tmp_TestZone AS temp;
This may help you.
Edited Question's answer:
If I understood your question correctly then please try below query to remove your Time Offset from the result...
SELECT SERIAL_NUMBER,
CONVERT(varchar(19),SWITCHOFFSET(TIME_FROM, '-05:00'),120) AS Result_date
FROM tmp_TestZone2
OR
SELECT SERIAL_NUMBER,
CONVERT(varchar(19),SWITCHOFFSET(TIME_FROM, UTC_offset),120) AS Result_date
FROM tmp_TestZone2
Maintain varchar(19) length according your DATETIME CONVERSION CODE (like 120).
I have a table with a set of business dates I need to select the max date per month and year tried using the last_day function but that returns the last day not the max date of that month.please help me out.
MAX is an aggregate function, so you need to figure out how to group all of the days of the month together. The easiest way to do that is apply a function that will return the same value for every day in that month. LAST_DAY would work, but I prefer TRUNC (with 'MM' specified).
SELECT MAX(your_column) FROM your_table GROUP BY TRUNC(your_column, 'MM')
I have a DateTime column. I want to extract all records, lets say, from 8:30 to 16:15 within a certain date range. My problem is that I need to compare hour and minute as a single time value. I can test the DATEPART for Greater or Less than some hours value, but if I then do that for minutes my query will fail if the later-in-the-day time has a smaller minutes value.
I have looked at INTERVAL, BETWEEN, DATEPART, DATEDIFF etc, but don't see quite how to to this without a "TimeOfDay" value that I can use across records of different dates.
I have tried subtracting the year, month and day parts of the date so that I can compare just the time of day, but when attmpting to subract, say, the year part of a date I get an overlfow error:
This part works:
select - cast( DATEPART(YEAR, CallTime) as integer) from history
This fails:
select DATEADD(YEAR, - cast( DATEPART(YEAR, CallTime) as integer), CallTime)
from history where calltime is not null
I have also tried casting the hours and minutes parts to chars, concatenating them and comparing to my target range, but this also fails.
I believe newer versions of SQL server may have a function to deal with this situation, but that's not available to me.
I hope and imagine there is a simple, obvious solution to this, but it's eluding me.
Try creating a "MinuteOfDay" function that calculates how many minutes have passed in the day based on a datetime.
CREATE FUNCTION dbo.[MinuteOfDay]
(
#dt datetime
)
RETURNS int
AS
BEGIN
RETURN (datepart(hh,#dt)*60) + datepart(mi,#dt)
END
then use the result of that function to filter.
select *
from MyTable t
where dbo.MinuteOfDay(t.SomeDateTimeColumn) between dbo.MinuteOfDay('1900-1-1 08:30:00') and dbo.MinuteOfDay('1900-1-1 16:15:00')
give this a shot:
DECLARE #StartDateTime datetime
,#EndDateTime datetime
--date range is ALL of January 1st up to & including 31st
SELECT #StartDateTime='2011/01/01'
,#EndDateTime='2011/01/31'
SELECT
*
FROM TableName t
WHERE
t.ColumnDate>=#StartDateTime AND t.ColumnDate<#EndDateTime+1 --date range
AND LEFT(RIGHT(CONVERT(char(19),t.ColumnDate(),120),8),5)>='08:30' --time range start
AND LEFT(RIGHT(CONVERT(char(19),t.ColumnDate(),120),8),5)<='16:15' --time range end
if you have an index on t.ColumnDate, this should be able to take advantage of it.
the "date range" part of the WHERE throws away rows that are not within the intended date range. The "time range start" part of the WHERE throws away rows that are to early in time and the "time range end" throws away rows that are to late.
DATETIME values can be cast as FLOAT. Actually, a DATETIME is stored as a FLOAT.
The whole part of the FLOAT is the days since '12/31/1899' (or something close). The fractional part is the number of hours divided by 24. So 0.5 = 12 Noon.
08:30 is 0.3541666667
16:15 is 0.6770833333
SELECT CAST(CAST('2011-03-25 08:30:00' AS DATETIME) AS FLOAT) = 40625.3541666667
SELECT CAST(CAST('2011-03-25 16:15:00' AS DATETIME) AS FLOAT) = 40625.6770833333
So you could write
SELECT * FROM users WHERE hire_date < 40625.3541666667
Using a DATETIME as FLOAT you can use whichever mathematical functions work best for your query.