How do I convert a value after using DATEADD with it - sql

I have a little query that strips the date from the datetime field but when I try to convert it from GMT to CST it readds the date. Is there a better way to do this?
Location table:
arrival
4-6-2018 12:35:43
SELECT arrival
FROM(
SELECT CONVERT(VARCHAR(8), arrival))
FROM locations
)a
This query will give me this result:
12:35:43
SELECT (DATEADD(hour,-5,arrival))
FROM(
SELECT CONVERT(VARCHAR(8), arrival))
FROM locations
)a
4-6-2018 12:35:43
This query will give readd the date. How can I remove the date and then do the dateadd function without it readding the date

arrival seems to be a DateTime, which always carries a date part. You need a time instead, supported by SQL Server 2008+:
cast(DATEADD(hour,-5,arrival) as time)

To quote from DATEADD (Transact-SQL) - Return Types:
The return data type is the data type of the date argument, except for string literals. The return data type for a string literal is datetime. An error will be raised if the string literal seconds scale is more than three positions (.nnn) or contains the time zone offset part.
Emphasis my own.
As you are passing a string (varchar), then DATEADD is returning a datetime.
Like those in the comments have said, if you use the correct data type (time) this problem goes away:
SELECT DATEADD(HOUR, -5,CONVERT(time,Arrival))
FROM (VALUES('4-6-2018 12:35:43'),('4-6-2018 07:35:43'),('4-6-2018 03:35:43')) V(Arrival)

Probably this is what you are asking for:
SELECT Convert(Varchar(8), DATEADD(hour,-5,arrival), 108)
FROM locations;
Note: This is compatible with SQL server versions that doesn't have Time datatype too.

Related

SQL, casting a string to date so I can use GETDATE()

I am using SQL Server Management Studio 18 against SQL Server 2016. I have some material that are in batches and those batches have expiration dates that are held as strings, but are basically in the format of 'yearmonthday', e.g. '20210312' for March 3rd, 2021. My goal is to only see material that is expiring after the current date. Whenever I try to CAST the expiration date column AS DATE within the WHERE clause, I get this error:
Conversion failed when converting date and/or time from character string
(or something similar when trying different methods).
So, right now my code looks like this:
SELECT MaterialColumn, BatchColumn, CAST(ExpirationColumn AS DATE)
FROM StockTable
WHERE CAST(ExpirationColumn AS DATE) > CAST(GETDATE() AS DATE)
If I don't do the WHERE clause, I know I can CAST the ExpirationColumn as DATE without issue, but when it's in the WHERE clause, I run into that error. Is there any way I can filter to see only the dates that I want?
You can use try_cast() instead:
SELECT MaterialColumn, BatchColumn, CAST(ExpirationColumn AS DATE)
FROM StockTable
WHERE TRY_CAST(ExpirationColumn AS DATE) > CAST(GETDATE() AS DATE);
You can also find the bad values:
SELECT ExpirationColumn
FROM StockTable
WHERE TRY_CAST(ExpirationColumn AS DATE) IS NULL AND ExpirationColumn IS NOT NULL;
It sounds like you might need to fix some data values.
Honestly, if your dates are all stored in the format yyyyMMdd then there's no need to convert. Instead use a varchar parameter, as (at least) a varchar in the format yyyyMMdd had the same sort order as a date.
As a result you just convert GETDATE to the right format:
WHERE Expiration > CONVERT(varchar(8), GETDATE(), 112)
Of course, this doesn't change my statements in the comment; fix your design, don't stores dates as a string but as a date (and time) data type.

Parse values of different type to date

I'm trying to parse certain columns into a date format and have had success doing so, but have run into an error due to inconsistency that lies in the data.
My date columns are currently integers in the form of YYYYMMDD, so I've used the following in the select statement to parse into dates:
CONVERT(datetime, CAST(date_column AS CHAR(8)), 112)
This works as expected, transforming my data into a YYYY-MM-DD format.
I run into the following error though:
Conversion failed when converting date and/or time from character
string.
After looking through the data a bit, it turns out I have some cases of inconsistent data values, such as -1 and 10630 instead of the expected YYYYMMDD value.
Do I just need to add a WHERE statement to only apply CONVERT and CAST to YYYYMMDD fields while filtering out fields with bad data? If so, how would I do this, or is there a better way?
Thanks in advance
Let me assume you are using SQL Server, based on the syntax of your SQL. You shouldn't actually need the 112. 'YYYYMMDD' is the default date format for SQL Server.
In any case, you can use TRY_CONVERT():
TRY_CONVERT(datetime, CAST(date_column AS CHAR(8)), 112)
This returns NULL if the value cannot be converted. You can find the offending values using:
select date_column
from t
where try_convert(datetime, cast(date_column as char(8)) is null and
date_column is not null;
Use Parse() or Try_parse()
select parse('22-JAN-1989' as date)
select parse('04-March-1992' as date)
select parse('03/10/2020' as date)
select parse('07-05-1958' as date)
select parse('Aug 25,2016' as date)
Every example above returns a valid date.
You can also add USING 'en-US' or such if you want a different culture.
If you are getting numeric values, and you know the starting date, use
select IsNull(try_parse('16500' as date),dateadd(d,cast('16500' as int),'1/1/1980'))

SQL How to format M/DD/YYYY (1/31/1960) to DD/MM/YYYY (31/01/1969)

I have a column that has date and time mixed together i.e. 1/31/1960 12:00:00AM and I would like to convert them into two-column through SQL function:
(a) DD/MM/YYYY i.e 31/01/1969
(b) HH:MM i.e 12:00
Thanks in advance.
Take a look at the CONVERT() function, specifically the style for datetime. Additionally, we can CAST() the DATETIME as a TIME data type to extract the time.
Assuming your original column is a DATETIME data type, you can run
SELECT
CONVERT(NVARCHAR(24),{DateField},103)
,CAST({DateField} AS TIME)
If it is string, you can cast it then convert
SELECT
CONVERT(NVARCHAR(24),CAST('1960-01-31' AS DATETIME),103) AS ReportingDate
,CAST(CAST('1960-01-31' AS DATETIME) AS TIME) AS ReportingTime
If you're on a sufficiently recent version of SQL Server, the FORMAT() function is your friend.
DECLARE #d DATE = GETDATE();
SELECT FORMAT(#d, 'dd/MM/yyyy');
Note, that second argument is a .NET formatting string, so you should be able to use whatever is available from the Framework.

SQL date formats

How can I convert this 201402110544 to date(2014-02-11) in SQL server 2008?
You can cast as DATE data type (https://msdn.microsoft.com/en-us/library/bb630352(v=sql.100).aspx)
SELECT CAST(datetime_value AS DATE)
SELECT CAST(GETDATE() AS DATE) --> 2015-08-18
If you have a string to cast as DATE you can use:
SELECT CAST(LEFT('201402110544', 8) AS DATE)
You trim out the time part, by taking 1st 8 chars (YYYYMMDD) and will result a valid string to cast as DATE.
If this format is always the same, you can do this
DECLARE #d VARCHAR(20)='201402110544'
SELECT CAST(SUBSTRING(#d,0,9) as DATETIME)
Also have a look at The ultimate guide to the datetime datatypes which explains in detail about handling date-times
String to date conversion sure is a weakness of SQL Server. CONVERT does that, but can only deal with a number of given formats. So you must convert your string into such a format first and then convert it to date afterwards.
One such format is 120 = 'yyyy-mm-dd hh:mi:ss' which I think comes closest to yours. Another 102 = 'yyyy.mm.dd' suffices to get the date.
convert(
date,
concat(substring(datestring, 1,4), '.',
substring(datestring, 5,2), '.',
substring(datestring, 7,2)),
102)
from data;
SQL fiddle: http://www.sqlfiddle.com/#!3/9eecb7/3689
EDIT: I stand corrected. Horia is right; CAST supports 'yyyymmdd', so you can use it directly by merely cutting of the string's time part. This is more readable than my suggestion above, which makes CAST the better option in your case.

How do I strip the date off of a datetime string in SQL SSIS?

I'm working on a data warehouse project and would like to know how to (preferably in a Derived Column component in a Data flow) strip the date piece off of a SQL datetime record.
Once I have the datetime converted to just a time I am going to do a lookup on the time to find the related time record in a time dimension table.
Can someone give me a simple function to accomplish this inside a derived column transform?
Example: Transform a datetime such as "12/02/2008 11:32:21 AM" into simply "11:32:21 AM".
I would just do a cast to DT_DBTIME type (using Derived Column transform, or Convert type transform). DT_DBTIME contains just (hours, minutes, seconds) part of the date/time, so you'll get rid of the date part.
If you need to do this in a variable expression Michael's solution won't work, but you can use the following expression:
(DT_DATE)(DT_DBDATE)GETDATE()
(DT_DBDATE) converts the current date and time to a date only. But the new datatype is not compatiple with SSIS's datetime. Therefore you'll have to use (DT_DATE) for converting to a compatible type.
Courtesy of this solution belongs to Russel Loski who has posted it in his blog:
http://www.bidn.com/blogs/RussLoski/ssas/1458/converting-datetime-to-date-in-ssis
Actually if you reverse the first 2 expressions like this: (DT_DBDATE)(DT_DATE)GETDATE()
instead of (DT_DATE)(DT_DBDATE)GETDATE(), then you will TRUNCATE the time off the date field.
If the DT_DATE expression is before the DT_DBDATE expression, you will still have the time portion in your output, but it will be reset to all zeroes.
Ran into this with writing a report for a scheduling app, needed the time that was stored as part of a datetime data type. I formated the datetime as 0 which gives you this mon dd yyyy hh:miAM (or PM), and just did a substring of that which returned the time only in an AM/PM format.
Example below.
DECLARE #S DATETIME = GETDATE()
SELECT SUBSTRING(CONVERT(NVARCHAR(30), #S , 0) , 13 , 10) AS ApptTime
, CONVERT(NVARCHAR(30), #S , 0) AS ApptDate
I personally use a series of functions for this. E.g.:
ALTER FUNCTION [dbo].[TIMEVALUE]
(
#Datetime datetime
)
RETURNS datetime
AS
BEGIN
RETURN (#Datetime - CAST(ROUND(CAST(#Datetime AS float), 0, 1) AS datetime))
END
I'd love to claim all the credit but it should really go to this guy.