SQL Varchar convert to Date - Sybase - sql

I am using Sybase IQ and have the following stored as a varchar:
01October 2010
I want to convert this from varchar to date datatype with the following format:
yyyy-mm-dd eg.2010-10-01
How would I write this SQL statement? Thanks in advance.

With difficulty. There's a reason you should never store dates and times as strings.
It's been awhile since I've used Sybase, but what we need to do is get the field into YYYY-MM-DD format, and then pass it to the DATE() or DATETIME() function.
Let's assume the first two characters are always the day of the month, and the last 4 characters are the year. That means everything in between is the month. Let's also assume that there are no leading or trailing spaces. If either of these assumptions fails, then the query will fail.
Then you can do something like this:
SELECT DATE (
RIGHT(UnnamedField,4) + '-' +
CASE LTRIM(RTRIM(SUBSTRING(Unnamed,3,LEN(Unnamed) - 6)))
WHEN 'January' THEN '01'
WHEN 'February' THEN '02'
WHEN 'March' THEN '03'
.
.
.
WHEN 'December' THEN '12'
END + '-' + LEFT(UnnamedField,2)
)
FROM UnnamedTable
Note that, as others have mentioned, the date data type is not a formatted datatype. If possible you should format it in your application. If you must do it in the query, use the CONVERT() function.

Sybase is able to convert a string to a date. So if you use substring to extract the date into a format that IQ can convert, then you can just use the convert() function.
Here's an example of how to do it:
Sample data:
create table #tmp1 (col1 varchar(100))
insert #tmp1 values ('01October 2010')
Query to convert the value to a date:
select
convert
(
date,
(
substring(col1, 3, charindex(' ', col1) - 2) -- Month
+ substring(col1, 1, 2) -- Day
+ substring(col1, charindex(' ', col1), 5) -- Year (include the leading space)
)
)
from #tmp1
Now that the value is in a date format, you can use the convert function to convert the date datatype to string, using your specified format. The default output for a date datatype is yyyy-mm-dd already.
Edit: After taking a look at #BaconBits' answer, I've realized that I could simplify the query a bit by using the substring function wrappers left, right, and the convert wrapper of date. It's the same logic; but using the simplified wrappers might make it easier to understand.
select
date
(
substring(col1, 3, charindex(' ', col1) - 2) -- Month
+ left(col1, 2) -- Day
+ ' ' + right(col1, 4) -- Year (include the leading space)
)
from #tmp1

Related

Convert nvarchar date (DD/MM/YYYY) to Date Period (YYYY_MM)

I am trying to convert this into a period format, so e.g. 2018_05 (YYYY_MM). currently the data is in DD/MM/YYYY format.
I tried a cast code but it returns me YYYY_DD.
SELECT
CASE WHEN RESERVED_FIELD_4 IS NULL THEN NULL
ELSE cast(year(RESERVED_FIELD_4) as Nvarchar (4))
+'_'+right('00'+cast(month(RESERVED_FIELD_4) as Nvarchar (2)),2)
END AS [DATAFEED_PERIOD]
I expect/want to see YYYY_MM.
Assuming RESERVED_FIELD_4 is a string type (char/nchar/varchar/nvarchar) the simplest solution would be to use substring:
CASE
WHEN RESERVED_FIELD_4 IS NULL THEN NULL
ELSE SUBSTRING(RESERVED_FIELD_4, 7, 4) + '_'+ SUBSTRING(RESERVED_FIELD_4, 4, 2)
END AS [DATAFEED_PERIOD]
If it's a date/datetime/datetime2 data type, the simplest solution would be to use format:
FORMAT(RESERVED_FIELD_4, 'yyyy_MM')
But for better performance you can use convert and stuff:
SELECT STUFF(CONVERT(char(6), RESERVED_FIELD_4, 112), 5, 0, '_')
In case your format is actually d/m/y the simplest option is to convert to date and than back to string:
SELECT STUFF(CONVERT(char(6), CONVERT(Date, RESERVED_FIELD_4, 103), 112), 5, 0, '_')
This is the common problem of storing a date with a VARCHAR column. You are guessing that the stored pattern is DD/MM/YYYY but the SQL engine doesn't know that and is currently assuming the MM/DD/YYYY pattern.
Please check these results:
-- MM/DD/YYYY
SELECT
DAY ('05/01/2019'), -- 1
MONTH('05/01/2019') -- 5
-- DD/MM/YYYY
SELECT
DAY ('25/05/2019'), -- Conversion failed when converting date and/or time from character string
MONTH('25/05/2019') -- Conversion failed when converting date and/or time from character string.
To display what you want correctly use string functions:
SELECT
RIGHT(RESERVED_FIELD_4, 4) + '_' + SUBSTRING(RESERVED_FIELD_4, 4, 2)
But you should actually fix the values on your VARCHAR column, cast them to DATE and store the values as DATE.
ALTER TABLE YourTable ADD ReservedField4Date DATE
UPDATE YourTable SET
ReservedField4Date = CONVERT(DATE,
RIGHT(RESERVED_FIELD_4, 4) -- Year
+ '-' + SUBSTRING(RESERVED_FIELD_4, 4, 2) -- Month
+ '-' + LEFT(RESERVED_FIELD_4, 2)) -- Day
ALTER TABLE YourTable DROP COLUMN RESERVED_FIELD_4
EXEC sp_rename 'SchemaName.YourTable.ReservedField4Date', 'RESERVED_FIELD_4', 'COLUMN'
Beware that changing the column type might affect other queries that assume this is a VARCHAR column.
If your data is in DD/MM/YYYY format, then it is being stored as a string. Hence, string functions come to mind:
select right(RESERVED_FIELD_4) + '_' + substrint(RESERVED_FIELD_4, 4, 2)
In SQL-SERVER you can use 'format'
format(dy,#your_date) as day_of_year
month(#your_date) as month
Try this:
Select concat(month(#your_date),'_'year(#your_date)) as your_period
this is a reference
Why not just do conversations ? :
SELECT REPLACE(CONVERT(VARCHAR(7), CONVERT(date, RESERVED_FIELD_4, 101), 102), '.', '_')
This assumes RESERVED_FIELD_4 is date type.

How to split dash-separated values in SQL Server

I have a date saved in an nvarchar type and I want to split the day, month and year into separate nvarchar variables (that means three variables). The date looks as follows: exposure_date ='2018-12-04' and the format is yyyy-dd-mm
any help please?
My whole project is stuck on this.
The "correct" answer here is to fix your datatype. When storing data always choose an appropriate data type for the data you're storing. For a date (with no time part) then the correct datatype is date. if you're storing numerical data, then use a numerical datatype, such as int or decimal. (n)varchar is not a one size fits all datatype and using it to store data that has a data type designed for it is almost always a bad choice. I'm storing the data as an (n)varchar because I need it in a specific format is never an excuse; have your presentation layer handle to display format, not your RDBMS.
The first step, therefore would be to change your string representation yyyy-dd-MM of a date to the ISO format yyyyMMdd by doing:
UPDATE YourTable
SET exposure_date = LEFT(exposure_date,4) + RIGHT(exposure_date,2) + SUBSTRING(exposure_date,6,2);
Now you have a unambiguous representation, you can change the data type of your column without concerns of incorrect implicit casts or error:
ALTER YourTable ALTER COLUMN exposure_date date;
Then, finally, you can treat your data as what it is, a date, and use the DATEPART function:
SELECT DATEPART(YEAR,exposure_date) AS Exposure_Year,
DATEPART(MONTH,exposure_date) AS Exposure_Month,
DATEPART(DAY,exposure_date) AS Exposure_Day
FROM YourTable;
You can also try the following
Declare #myDate date
select #myDate= Cast(substring('2011-29-12', 1, 4)
+ '-' + substring('2011-29-12', 9, 2)
+ '-' + substring('2011-29-12', 6, 2)
as Date) --YYYY-MM-DD
Select #myDate as DateTime,
datename(day,#myDate) as Date,
month(#myDate) as Month,
datename(year,#myDate) as Year,
Datename(weekday,#myDate) as DayName
The output is as shown below
DateTime Date Month Year DayName
--------------------------------------------
2011-29-12 29 12 2011 Thursday
You can find the live demo here
You can try below -
select concat(cast(year(cast('2018-12-04' as date)) as varchar(4)),'-',
cast(month(cast('2018-12-04' as date)) as varchar(2)), '-',
cast(day(cast('2018-12-04' as date)) as varchar(2)))
from tablename
If you have fixed format, then you could use this simple query with substring method:
select substring(dt, 1, 4) + '-' +
substring(dt, 9, 2) + '-' +
substring(dt, 6, 2) [YYYY-MM-DD]
from (values ('2018-31-12')) tbl(dt)
Let's go directly to the main issue, which is you are using the wrong datatype to store dates, you should store them as DATE, the datatypes are there for a reason and you need to choose a proper one for your column.
So, you need to ALTER your table and change the column datatype to DATE instead of NVARCHAR datatype.
ALTER <Table Name Here>
ALTER COLUMN <Column Name Here> DATE;
Then all things will easy, you just run the following query to get the desired output
SELECT YEAR(<Column Name Here>) TheYear,
MONTH(<Column Name Here>) TheMonth,
DAY(<Column Name Here>) TheDay
FROM <Table Name Here>
Which is the right and the best solution.
You can also (if you are not going to alter your table) do as
CREATE TABLE Dates(
StrDate NVARCHAR(10)
);
INSERT INTO Dates VALUES
(N'2018-12-04'),
(N'Invalid');
SELECT LEFT(StrDate, 4) StrYear,
SUBSTRING(StrDate, 6, 2) StrMonth,
RIGHT(StrDate, 2) StrDay
FROM Dates;
OR
SELECT YEAR(StrDate) StrYear,
MONTH(StrDate) StrMonth,
DAY(StrDate) StrDay
FROM (
SELECT TRY_CAST(StrDate AS DATE) StrDate
FROM Dates
)T

Output year and month with a string

Trying to output something like:
2016,11
Using this:
SELECT
CONVERT(VARCHAR(20),YEAR(GETDATE()) + ',' + MONTH(GETDATE())) AS YearMonth
Am I missing something in convert? Because I am getting this error:
Conversion failed when converting the varchar value ',' to data type
int.
Thanks
Try this.
SELECT
CONVERT(VARCHAR(20),YEAR(GETDATE())) + ',' + CONVERT(VARCHAR(20), MONTH(GETDATE())) AS YearMonth
You might use CONVERT with 112 to reach a string without delimiters ("20161110"). Converting this to VARCHAR(*6*) will implicitly cut the day. One (in most cases positiv) side-effect: You will get a low month zero padded (e.g. 2016,04). Then I use STUFF to insert the ,:
SELECT STUFF(CONVERT(VARCHAR(6),GETDATE(),112),5,0,',')
If you do not like the zero padded month, you could replace the 0 in STUFF like this:
DECLARE #d DATETIME={d'2016-04-05'};
SELECT STUFF(CONVERT(VARCHAR(6),#d,112),5,CASE WHEN MONTH(#d)<10 THEN 1 ELSE 0 END,',')
You are missing converting the output of MONTH() to a string. Here is one method:
select datename(year, getdate()) + ',' + cast(month(getdate()) as varchar(255)) as YearMonth
datename() is convenient because it returns a string. Unfortunately, for month it returns the name of the month, rather than the number.
You could also do:
select replace(convert(varchar(7), getdate(), 120), '-', ',')
Or use format() in SQL Server 2012+:
select format(getdate(), 'yyyy,MM')

How to store hour datepart in SQL in table

I have a table with 2 columns: Customer_ID, which is a string, identifying each client and Time_id: a string with 14 characters, identifying timestamp of a transaction. Example:
Customer_id; Time_id
12345; 20140703144504
I want to be able to use datediff in hours datepart, but I can´t seem to be able to convert time_id properly. I use the following query:
update transation_table
set time_id= (
convert(timestamp, time_id)
)
It works, but removes hours datepart, which is what I need. For day datepart I can do it, converting to datetime. How can I keep in the table the hh?
edit: I´m running MS SQL Server 2014.
best regards
Using the convert and string concatenation below, you can use DATEPART on the resulting value.
DECLARE #tmp TABLE(
Customer_id VARCHAR(50),
Time_id VARCHAR(50)
)
INSERT INTO #tmp
SELECT '12345','20140703144504'
select
*,CONVERT(DATETIME,
SUBSTRING(Time_id,5,2) + '/' +
SUBSTRING(Time_id,7,2) + '/' +
SUBSTRING(Time_id,1,4) + ' ' +
SUBSTRING(Time_id,9,2) + ':' +
SUBSTRING(Time_id,11,2) + ':' +
SUBSTRING(Time_id,13,2)
,101
)
from #tmp
Use FORMAT to get a string representation of the value in a supported format (ODBC canonical in the Date and Time styles chart), then use TRY_CONVERT to return an actual datetime value:
SELECT TRY_CONVERT(DATETIME,
FORMAT(CAST('20140703144504' AS BIGINT),
'####-##-## ##:##:##'),
120);
This requires SQL Server 2012+.
As mentioned elsewhere, the data should be stored in a single datetime2 column, or paired date and time columns. The above functions can be used to help convert existing data to the new column(s).

query to search dates which are stored as string in the database

I have a table where I store an activity completion date as varchar. The format of the date stored is MM/DD/YYYY HH:MM:SS.
I have search window where I have two fields Completion date from and completion date to.The date format selected here is MM/DD/YYYY.
How do I write a query such that I am able to fetch the activity completion between two given dates from the table which has the dates stores as varchar.This table was created a long time back and no thought was given to saving dates as datetime.
You can use SQL CONVERT to change your columns to DATE format but that will cause performance issues.
SELECT *
FROM MyTable
WHERE CONVERT(DATETIME, MyDate) >= CONVERT(DATE, '01/01/2014')
AND CONVERT(DATETIME, MyDate) <= CONVERT(DATE, '01/31/2014')
CONVERT documentation - http://msdn.microsoft.com/en-us/library/ms187928.aspx
if you are unable to change how data is stored, than for better performance , you can create view with calculated column that converts VARCHAR to DATETIME. After that can create index on calculated column. Index on Computed Column documentation
Use the SUBSTRING function to get the date parts in a comparable order (i.e. yyyymmdd):
select *
from mytable
where
CONCAT( SUBSTRING(thedate, 7, 4) , SUBSTRING(thedate, 4, 2) , SUBSTRING(thedate, 1, 2) )
between
CONCAT( SUBSTRING(#FROMDATE, 7, 4) , SUBSTRING(#FROMDATE, 4, 2) , SUBSTRING(#FROMDATE, 1, 2) )
and
CONCAT( SUBSTRING(#TODATE, 7, 4) , SUBSTRING(#TODATE, 4, 2) , SUBSTRING(#TODATE, 1, 2) )
;
You could use this code :
select * from table_name
where CAST(col1 as date )
between CAST(Completion date from as date )
and CAST(Completion date to as date);
Function syntax CAST:
CAST ( expression AS data_type )
You can use below if the date format is {yyyy-MM-dd}, or you can adjust the charindex's index value depending on format
SELECT *
FROM table
WHERE
CHARINDEX('-', col_value, 0) = 5
AND CHARINDEX('-', col_value, 6) = 8
AND LEN(col_value) = 10
The above piece will look for first occurrence of char '-' at position 5 and the second char '-' at position 8 while the entire date value's length is equal to 10 chars
This is not full proof, but will narrow down the search. If you want to add time then just expand the criteria in the where to accommodate the format i.e. {yyyy-MM-dd 00:00:00.000}
This is a safe way to query the data, without any unexpected 'invalid cast / convert' errors.