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

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.

Related

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

SQL - Convert to date

I have a numeric column in SQL which I need to convert to a date. The field is currently coming into the database as: "20181226.00000".
I only need to the characters before the " . ". So i did a SUBSTRING - CHARINDEX looking for anything before the " . " . I then did a cast as NVARCHAR.
Now I'm getting 20181226 but I want this date field to populate like:
"MM/DD/YYYY" .
My current SQL is:
CONVERT(VARCHAR(10),SUBSTRING(CAST('MYFIELD' AS NVARCHAR(50)) ,0, CHARINDEX('.', 'MYFIELD' , 0)),101)
Just change 101 to 103
CONVERT(VARCHAR(10),SUBSTRING(CAST('MYFIELD' AS NVARCHAR(50)) ,0, CHARINDEX('.', 'MYFIELD' , 0)),101)
The easiest way is to convert it to what it actually is, a date, and then back to a varchar using the right style.
SELECT convert(varchar(max), convert(date, substring(convert(varchar(max), nmuloc), 1, charindex('.', convert(varchar(max), nmuloc)) - 1)), 101)
FROM elbat;
I wasn't sure if it's a number or a string. If it's a string you don't need the convert(varchar(max), nmuloc)s.
However a side note: You should not store dates as numbers or strings. Use an appropriate data type like date.
Or you could achieve it like this.
declare #v_value numeric(18,5)=20181226.00000
SELECT SUBSTRING(CAST(CAST(#v_value AS INT) AS VARCHAR),5,2)+'/'+SUBSTRING(CAST(CAST(#v_value AS INT) AS VARCHAR),7,2)+'/'+SUBSTRING(CAST(CAST(#v_value AS INT) AS VARCHAR),1,4) as V_OUTPUT
--Output
/*
V_OUTPUT
------------------
12/26/2018
*/
Best Regards,
Will
First we have convert to varchar and then Date format
SELECT CONVERT(varchar, CAST(CAST('20181206.00000' as VARCHAR(8)) AS DATE), 103); dd/mm/yyyy
SELECT CONVERT(varchar, CAST(CAST('20181206.00000' as VARCHAR(8)) AS DATE), 101); mm/dd/yyyy

SQL Varchar convert to Date - Sybase

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

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.

Computed column

In current table I have a column that holds the date field in ddmmyyyy format and it is of type varchar(8). The column has some string value also. I want to create a computed column that will hold the value in DateTime format if the value in source column is valid date time.
Assuming your varchar(8) column is dateString :
Cast([dateString] as datetime)
SQL Server prefers dates in the format of yyyymmdd so there will be some string manipulation involved to format your data like this. We should also use the IsDate function to make sure we have a valid date.
So:
Cast(Case When IsDate(Right(#Data, 4)
+ SubString(#Data, 3, 2)
+ Left(#Data, 2)) = 1
Then Right(#Data, 4)
+ SubString(#Data, 3, 2)
+ Left(#Data, 2) End As DateTime)
Notice that this code should correctly handle invalid dates contained within your varchar column. If a date is invalid, this code will return NULL.
try parsing your varchar into dd/mm/yyyy before attempting the cast:
cast(substring([datestring],1,2) + '/' +
substring([datestring],3,2) + '/' +
substring([datestring],5,4) as datetime)