I have four columns namely-
1. C_Date in YYYYMMDD format (varchar(255)) Eg. 20161231
2. C_Time in 4-digit Military format (varchar(255)) Eg. 2143
3. E_Date in YYYYMMDD format (varchar(255)) Eg. 20161230
4. E_Time in 4-digit Military format (varchar(255)) Eg. 1600
I want to Calculate the time between E event and C event. How can i perform this computation with a select statement?
Pretty simple to create a date type from the component values:
with data as (select '20161231' as c_date, '2143' as c_time)
select
convert(
datetime,
stuff(stuff(stuff(c_date + ' ' + c_time, 12, 0, ':'), 7, 0, '-'), 5, 0, '-'),
120
) as c_datetime
from data;
Use datediff() to calculate the time difference. You didn't specify how you wanted the output to look so I won't attempt a guess. There should be a hundred other questions out there with information relevant to your question though.
Also note that I did not append ':00' to the string to represent seconds. It seems to work though I couldn't track down an official document to confirm that. So to be safe you may want to tack that on as well. Arguably there could be a more universal format like ISO 8601 that would be a "better" solution. You get the idea though.
A small matter to convert your strings into a datetime. Then we use DateDiff() to calculate the differance between the two dates.
Declare #YourTable table (C_Date varchar(255),C_Time varchar(255),E_Date varchar(255),E_Time varchar(255))
Insert Into #YourTable values
('20161231','2143','20161230','1600')
;with cte as (
Select *
,CDT = try_convert(DateTime,C_Date+' '+stuff(C_Time,3,0,':'))
,EDT = try_convert(DateTime,E_Date+' '+stuff(E_Time,3,0,':'))
from #YourTable
)
Select CDT
,EDT
,Duration = concat(DateDiff(DD,EDT,CDT),' ',Format(DateAdd(Second,DateDiff(SECOND,EDT,CDT),'1899-12-31'),'HH:mm:ss'))
,AsSeconds = DateDiff(SECOND,EDT,CDT)
,AsMinutes = DateDiff(MINUTE,EDT,CDT)
From cte
Returns
CDT EDT Duration AsSeconds AsMinutes
2016-12-31 21:43:00 2016-12-30 16:00:00 1 05:43:00 106980 1783
Related
I am trying to convert date to number like below, not sure which function works better.
Database used is SQL Server.
Table details
create table test
(
id varchar(255),
call_date varchar(255)
);
insert into test('26203', '14-Aug-2020');
I need output as 4405726203 -- its concatenation of date (14-Aug-2014) + id (26203)
This is too long for a comment.
SQL Server allows you to convert a datetime to a float. That would be:
select cast(dte as float)
from (values (convert(datetime, '14-Aug-2020'))) v(dte)
However, the corresponding floating point value is 44055 (https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=d142a64db0872e7572eb4fbd6d5d5fe7). It is a bit of mystery what your intention is.
You could subtract 2, but that seems arbitrary. You could calculate the number of days since 1899-12-30. But that also seems arbitrary.
In any case, once you figure out how to convert the date to the number you want, just use concat() to combine the values.
I have found the solution:
convert(varchar,CAST(CONVERT(datetime,call_date) as bigint)) + id
Under the hood, a SQL Server DateTime is a tuple of 2 32-bit integers:
The first integer is a count of days since since the epoch, which for SQL Server is 1 January 1900
The second integer is a count of milliseconds since start of day (00:00:00.000). Except that the count ticks up in 3- or 4-milliscond increments. Microsoft only knows why that decision was made.
You can get the count of days since the epoch with
convert( int, convert( date, t.call_date ) )
[wrap that in convert(varchar, ... ) to turn it into a string]
Looks like your id is already a varchar, so you can say:
select compound_key = convert(varchar,
convert(int,
convert(date,
call_date
)
)
)
+ t.id
from test t
I would suggest padding both fields with leading zeros to a fixed length so as to avoid possible collisions (assuming you're trying to generate a key here). Signed 32-bit integer overflows a 2.1 billion-ish, so 9 digits for each field is sufficient.
This works
select concat(datediff(d, 0, cast(call_date as date)), id)
from
(values ('26203','14-Aug-2020')) v(id, call_date);
Results
4405526203
I have a varchar column with the following format ddmmyyyy and I'm trying to convert it to date in the format dd-mm-yyyy. I'm using the query below but I get the error:
Conversion failed when converting date and/or time from character string.
select *, coalesce(try_convert(date, newdate, 105), convert(date, newdate))
from mydate
You don't have a date, you have a string. So, you can use string operations:
select stuff(stuff(newdate, 5, 0, '-'), 3, 0, '-')
If you want to convert to a date, you can do:
select convert(date, concat(right(newdate, 4), substring(newdate, 3, 2), left(newdate, 2)))
You could then format this as you want.
However, you should not be converting the value to a date. You should be storing it as a date in the first place.
To turn your string to a date, you can just [try_]cast() it; SQL Server is usually flexible enough to figure out the format by itself:
try_cast(newdate as date)
If you want to turn it back to a string in the target format, then you can use format():
format(try_cast(newdate as date), 'dd-MM-yyyy')
Compared to pure string operations, the upside of the try_cast()/format() approach is that it validates that the string is a valid date in the process.
Have to agree with the others. Why are you storing a date as a string in the first place? In a non-standard format, no less? Here's one way, but you should really fix the data model. Store dates as dates.
DECLARE #badIdea table (dt char(8));
INSERT #badIdea(dt) VALUES('21052020');
SELECT newdate = TRY_CONVERT(date, RIGHT(dt,4) + SUBSTRING(dt,3,2) + LEFT(dt,2))
FROM #badIdea;
BTW 105 won't work because it requires dashes. This works:
SELECT CONVERT(date, '21-05-2020', 105);
That's a bad format too, IMHO, because who knows if 07-08-2020 is July 8th or August 7th. But at least that one is supported by SQL Server. Your current choice is not.
SQL doesn't store date data types in different formats, and it's probably not a good idea to try and adjust this.
If, however, you are wanting a result set to simply display the date in a different format, you are on the right track. You just need to convert your date data type to a string.
SELECT *
, COALESCE ( TRY_CONVERT ( CHAR(10), newdate, 105 ), CONVERT ( CHAR(10), newdate ) )
FROM mydate
I have column of 24 hr and i need to change it to 12 hr, Please help .
Start time
174300
035800
023100
The result should be
Start time
05.43 PM
03.58 AM
02.31 AM
Use STUFF function to convert string to Time format
SELECT CONVERT(VARCHAR,CAST(STUFF(STUFF(ColumnName,3,0,':'),6,0,':') AS TIME),100)
Using one of the examples above - the following will work.
You need to split the data into hours/minutes and cast it to time format, than convert it to the relevant type:
declare #data int
set #data = 174300
select convert(VARCHAR(15),cast(cast(left(#data, 2 )as varchar(2)) + ':' + cast(substring(cast(#data as nvarchar(6)), 3,2 )as varchar(2) ) as time),100)
Don't store time as varchar, instead alter your table and change the column type to datetime.
SELECT right(convert(varchar(25), Start Time, 100), 7)
The 100 you see in the function specifies the date format mon dd yyyy hh:miAM (or PM), and from there we just grab the right characters.
You can see more about converting datetimes here.
I am being supplied a single integer that is supposed to represent an hour. So If it returns 1 it is 1:00 am and so forth on a 24 hour clock,13 for example is 1:00 pm. I need to convert this into time in SQL.
I know in MYSQL they have a function which does this:
SEC_TO_TIME(TheHour*60*60)
Is there an equivalent I can use in SQL? How do I do this?
You could do something like this.
select cast(DATEADD(hour, 13, 0) as time)
The upside is that it will still work even with negative numbers or values over 24.
There are two T-SQL function:
DATEFROMPARTS ( year, month, day )
and
TIMEFROMPARTS ( hour, minute, seconds, fractions, precision )
then you can use CONVERT if you need to format it.
-- test data
declare #hour_table table(hour_number int)
while (select count(*) from #hour_table) < 24
begin
insert into #hour_table(hour_number)
select count(*) from #hour_table
end
-- return results with your conversion to time string
select
hour_number,
convert(varchar(8),timefromparts( hour_number, 0, 0, 0, 0 ),0) as time_string
from #hour_table
I got a column called DateOfBirth in my csv file with Excel Date Serial Number Date
Example:
36464
37104
35412
When i formatted cells in excel these are converted as
36464 => 1/11/1999
37104 => 1/08/2001
35412 => 13/12/1996
I need to do this transformation in SSIS or in SQL. How can this be achieved?
In SQL:
select dateadd(d,36464,'1899-12-30')
-- or thanks to rcdmk
select CAST(36464 - 2 as SmallDateTime)
In SSIS, see here
http://msdn.microsoft.com/en-us/library/ms141719.aspx
The marked answer is not working fine, please change the date to "1899-12-30" instead of "1899-12-31".
select dateadd(d,36464,'1899-12-30')
You can cast it to a SQL SMALLDATETIME:
CAST(36464 - 2 as SMALLDATETIME)
MS SQL Server counts its dates from 01/01/1900 and Excel from 12/30/1899 = 2 days less.
tldr:
select cast(#Input - 2e as datetime)
Explanation:
Excel stores datetimes as a floating point number that represents elapsed time since the beginning of the 20th century, and SQL Server can readily cast between floats and datetimes in the same manner. The difference between Excel and SQL server's conversion of this number to datetimes is 2 days (as of 1900-03-01, that is). Using a literal of 2e for this difference informs SQL Server to implicitly convert other datatypes to floats for very input-friendly and simple queries:
select
cast('43861.875433912' - 2e as datetime) as ExcelToSql, -- even varchar works!
cast(cast('2020-01-31 21:00:37.490' as datetime) + 2e as float) as SqlToExcel
-- Results:
-- ExcelToSql SqlToExcel
-- 2020-01-31 21:00:37.490 43861.875433912
this actually worked for me
dateadd(mi,CONVERT(numeric(17,5),41869.166666666664)*1440,'1899-12-30')
(minus 1 more day in the date)
referring to the negative commented post
SSIS Solution
The DT_DATE data type is implemented using an 8-byte floating-point number. Days are represented by whole number increments, starting with 30 December 1899, and midnight as time zero. Hour values are expressed as the absolute value of the fractional part of the number. However, a floating point value cannot represent all real values; therefore, there are limits on the range of dates that can be presented in DT_DATE. Read more
From the description above you can see that you can convert these values implicitly when mapping them to a DT_DATE Column after converting it to a 8-byte floating-point number DT_R8.
Use a derived column transformation to convert this column to 8-byte floating-point number:
(DT_R8)[dateColumn]
Then map it to a DT_DATE column
Or cast it twice:
(DT_DATE)(DT_R8)[dateColumn]
You can check my full answer here:
Is there a better way to parse [Integer].[Integer] style dates in SSIS?
Found this topic helpful so much so created a quick SQL UDF for it.
CREATE FUNCTION dbo.ConvertExcelSerialDateToSQL
(
#serial INT
)
RETURNS DATETIME
AS
BEGIN
DECLARE #dt AS DATETIME
SELECT #dt =
CASE
WHEN #serial is not null THEN CAST(#serial - 2 AS DATETIME)
ELSE NULL
END
RETURN #dt
END
GO
I had to take this to the next level because my Excel dates also had times, so I had values like this:
42039.46406 --> 02/04/2015 11:08 AM
42002.37709 --> 12/29/2014 09:03 AM
42032.61869 --> 01/28/2015 02:50 PM
(also, to complicate it a little more, my numeric value with decimal was saved as an NVARCHAR)
The SQL I used to make this conversion is:
SELECT DATEADD(SECOND, (
CONVERT(FLOAT, t.ColumnName) -
FLOOR(CONVERT(FLOAT, t.ColumnName))
) * 86400,
DATEADD(DAY, CONVERT(FLOAT, t.ColumnName), '1899-12-30')
)
In postgresql, you can use the following syntax:
SELECT ((DATE('1899-12-30') + INTERVAL '1 day' * FLOOR(38242.7711805556)) + (INTERVAL '1 sec' * (38242.7711805556 - FLOOR(38242.7711805556)) * 3600 * 24)) as date
In this case, 38242.7711805556 represents 2004-09-12 18:30:30 in excel format
In addition of #Nick.McDermaid answer I would like to post this solution, which convert not only the day but also the hours, minutes and seconds:
SELECT DATEADD(s, (42948.123 - FLOOR(42948.123))*3600*24, dateadd(d, FLOOR(42948.123),'1899-12-30'))
For example
42948.123 to 2017-08-01 02:57:07.000
42818.7166666667 to 2017-03-24 17:12:00.000
You can do this if you just need to display the date in a view:
CAST will be faster than CONVERT if you have a large amount of data, also remember to subtract (2) from the excel date:
CAST(CAST(CAST([Column_With_Date]-2 AS INT)AS smalldatetime) AS DATE)
If you need to update the column to show a date you can either update through a join (self join if necessary) or simply try the following:
You may not need to cast the excel date as INT but since the table I was working with was a varchar I had to do that manipulation first. I also did not want the "time" element so I needed to remove that element with the final cast as "date."
UPDATE [Table_with_Date]
SET [Column_With_Excel_Date] = CAST(CAST(CAST([Column_With_Excel_Date]-2 AS INT)AS smalldatetime) AS DATE)
If you are unsure of what you would like to do with this test and re-test! Make a copy of your table if you need. You can always create a view!
Google BigQuery solution
Standard SQL
Select Date, DATETIME_ADD(DATETIME(xy, xm, xd, 0, 0, 0), INTERVAL xonlyseconds SECOND) xaxsa
from (
Select Date, EXTRACT(YEAR FROM xonlydate) xy, EXTRACT(MONTH FROM xonlydate) xm, EXTRACT(DAY FROM xonlydate) xd, xonlyseconds
From (
Select Date
, DATE_ADD(DATE '1899-12-30', INTERVAL cast(FLOOR(cast(Date as FLOAT64)) as INT64) DAY ) xonlydate
, cast(FLOOR( ( cast(Date as FLOAT64) - cast(FLOOR( cast(Date as FLOAT64)) as INT64) ) * 86400 ) as INT64) xonlyseconds
FROM (Select '43168.682974537034' Date) -- 09.03.2018 16:23:28
) xx1
)
For those looking how to do this in excel (outside of formatting to a date field) you can do this by using the Text function https://exceljet.net/excel-functions/excel-text-function
i.e.
A1 = 132134
=Text(A1,"MM-DD-YYYY") will result in a date
This worked for me because sometimes the field was a numeric to get the time portion.
Command:
dateadd(mi,CONVERT(numeric(17,5),41869.166666666664)*1440,'1899-12-31')