Bring correct date format in SSIS - sql-server

I need date format in American Format i.e. 9/30/2018; 8/31/2018; 7/31/2018.. so on and so forth in SSIS. I have written the code in the format as
LEFT((DT_STR,50,1252)DATEADD("d",-DAY(GETDATE()),GETDATE()),10)
This is bringing date in 2018-09-30 which is not the proper format. I do have given the data type as "STRING" as the above code doesn't take "DATE/DATE-TIME" as data type.
I am trying to bring the previous month last date and hence the format currently being fetched is not right.
Any guesses?
Thanks!

For a format like this, the date parts will need to be extracted from the date and concatenated accordingly. The expression below will convert the date to the DD/MM/YYYY format. Since you only listed single digits for the month in your question, this example does not account for zeros and the length will vary. If you want zeros added to single digit days and months, a "0" (with quotes) will need to be appended before the day and month.
RIGHT((DT_STR, 2, 1252) DATEPART("MM", DATEADD("D",-DAY(GETDATE()),GETDATE())), 2)
+ "/" + RIGHT((DT_STR, 2, 1252) DATEPART("DD", DATEADD("D",-DAY(GETDATE()),GETDATE())), 2)
+ "/" + (DT_STR, 4, 1252) DATEPART("YYYY", DATEADD("D",-DAY(GETDATE()),GETDATE()))

How about that
DECLARE #AsStr VARCHAR(10) = '2018-09-30', --If you store it as string
#AsDate DATE = '2018-09-30'; --If you store it as date
SELECT CONVERT(VARCHAR(10), #AsDate, 101) AsStr,
CONVERT(VARCHAR(10), CAST(#AsStr AS DATE), 101) AsDate;
Returns
+------------+------------+
| AsStr | AsDate |
+------------+------------+
| 09/30/2018 | 09/30/2018 |
+------------+------------+
Or you can use FORMAT() function as
SELECT
FORMAT(CAST(#AsStr AS DATE), 'MM/dd/yyyy') FormatStr,
FORMAT(#AsDate, 'MM/dd/yyyy') FormatDate;
Returns
+------------+------------+
| FormatStr | FormatDate |
+------------+------------+
| 09/30/2018 | 09/30/2018 |
+------------+------------+

You can use DATEFROMPARTS to get the first day of the month fairly easily. Then, you can use DATEADD to subtract a day, then CONVERT to output the 101 format which is in the form MM/DD/YYYY.
For example:
DECLARE #DT_STR Date = '2018-10-23'
SELECT CONVERT(varchar, DATEADD(DAY, -1, DATEFROMPARTS(YEAR(#DT_STR), MONTH(#DT_STR), 1)), 101) AS [answer]
Produces output:
answer
09/30/2018

Related

Get HH:MM:SS from a datetime in MSSQL

I have the following issue:
I have a datetime field, which contains entries like this: "1970-01-01 22:09:26.000"
I would like to extract only the 22:09:26 (hh:mm:ss) part, but I am unable to convert it into 24h format, I used FORMAT and CONVERT, but received the the am/pm culture (for the CONVERT I tried to use 13 culture value).
What is the simplest way to construct the formula to give back the above mentioned format?
Thank you!
1st way
You can select the format you wish from https://www.mssqltips.com/sqlservertip/1145/date-and-time-conversions-using-sql-server/
select replace(convert(nvarchar(20), CAST('1970-01-01 22:09:26.000' AS datetime), 114),'-',':')
2nd way
It is not a conversion,but if your entries are all the same format then you can use the below:
select right('1970-01-01 22:09:26.000',12)
Updated if you have null dates as well:
1.
select case when value is not null
then replace(convert(nvarchar(20), CAST(value AS datetime), 114),'-',':')
else null
end
select case when value is not null then right(value,12)
else null end
To get just the time portion of a datetime you just need to cast or convert it into the appropriate data type. If you really want to be formatting your data right in the query, this is very possible with format and I am not sure what issues you were facing there:
declare #t table(d datetime);
insert into #t values(dateadd(minute,-90,getdate())),(dateadd(minute,-60,getdate())),(dateadd(minute,-30,getdate())),(dateadd(minute,90,getdate()));
select d
,cast(d as time) as TimeValue
,format(d,'HH:mm:ss') as FormattedTimeValue
from #t;
Output
+-------------------------+------------------+--------------------+
| d | TimeValue | FormattedTimeValue |
+-------------------------+------------------+--------------------+
| 2020-08-10 11:51:15.560 | 11:51:15.5600000 | 11:51:15 |
| 2020-08-10 12:21:15.560 | 12:21:15.5600000 | 12:21:15 |
| 2020-08-10 12:51:15.560 | 12:51:15.5600000 | 12:51:15 |
| 2020-08-10 14:51:15.560 | 14:51:15.5600000 | 14:51:15 |
+-------------------------+------------------+--------------------+
By using format code as 108 we can get datetime in 'HH:mm:ss' format.
DECLARE #now DATETIME = GETDATE()
SELECT CONVERT(NVARCHAR(20), #now, 108)

Converting a NVARCHAR into a UK date

I'm looking to convert a users input that will be a NVARCHAR to a UK date
The user's input will always be a maximum of 6 digits.
For example:
151119 (DDMMYY) --> 15NOV19
120119 (DDMMYY) --> 12JAN19
You need a valid DATE or DATETIME / DATETIME2 value first. You can get this value using this SELECT query with CONVERT:
SELECT CONVERT(DATE,
SUBSTRING('151119', 3, 2) + '-'
+ SUBSTRING('151119', 1, 2) + '-'
+ SUBSTRING('151119', 5, 2)
, 10);
Now you have two possibilities to get the date in the expected format (DDMMMYY).
1 - solution using DATENAME:
-- set the date value (from custom date value).
DECLARE #dDateValue AS DATE = CONVERT(DATE,
SUBSTRING('150419', 3, 2) + '-'
+ SUBSTRING('150419', 1, 2) + '-'
+ SUBSTRING('150419', 5, 2)
, 10);
-- format the date value to the expected format.
SELECT DATENAME(DD, #dDateValue) +
UPPER(LEFT(DATENAME(MM, #dDateValue), 3)) +
RIGHT(DATENAME(YY, #dDateValue), 2);
2 - solution using CONVERT:
-- set the date value (from custom date value).
DECLARE #dDateValue AS DATE = CONVERT(DATE,
SUBSTRING('150419', 3, 2) + '-'
+ SUBSTRING('150419', 1, 2) + '-'
+ SUBSTRING('150419', 5, 2)
, 10);
-- format the date value to the expected format.
SELECT UPPER(REPLACE(CONVERT(VARCHAR, #dDateValue, 6), ' ', ''));
demo on dbfiddle.uk
Note: I recommend to store the date values on columns with DATE or DATETIME data type. You can format the date value on your application or using format functions on SQL-Server directly.
You need to alter the string into something that looks even little like a normal date format, then you can use convert:
declare #textDate nvarchar(6) = '120119';
select #textDate
, stuff(stuff(#textDate, 3,0,'/'), 6,0,'/')
, convert(date, stuff(stuff(#textDate, 3,0,'/'), 6,0,'/'), 3);
Gives:120119,12/01/19,2019-01-12
As that last one is a valid date datatype, you can now use Format().
Though obviously 2 digit years are a bad idea in the first place.
Forgot to say, the 3 is for UK 2 digit format(dd/mm/yy), and you can see the other choices here.
I highly recommend to work with date values on columns AS DATE or DATETIME type. This is a simple implementation for your need :
SQL Fiddle
MS SQL Server 2017 Schema Setup:
create table test (mydate nvarchar(6))
insert into test (mydate)values('151119')
insert into test (mydate)values('120119')
Query 1:
select FORMAT(CONVERT(DATE, dates), 'dd/MM/yyyy ') from (select left(mydate,2)
+
CASE SUBSTRING(mydate, 3, 2)
WHEN '01' THEN 'JAN'
WHEN '02' THEN 'FEB'
WHEN '03' THEN 'MAR'
WHEN '04' THEN 'APR'
WHEN '05' THEN 'MAY'
WHEN '06' THEN 'JUN'
WHEN '07' THEN 'JUL'
WHEN '08' THEN 'AUG'
WHEN '09' THEN 'SEP'
WHEN '10' THEN 'OCT'
WHEN '11' THEN 'NOV'
WHEN '12' THEN 'DEC'
ELSE 'error'
END
+ right(mydate,2) AS 'dates'
from test ) AS T
Results:
| |
|-------------|
| 15/11/2019 |
| 12/01/2019 |

How to get count of number of days left in month from given date

I want the count of number of days from 25/02/2019 in month of February and expected result is 4
I tried using master..spt_values in sql server but did not get expected result
declare #fdays int ,#d date=cast('20190201' as date),#JoinDate date=cast('20190225' as date)
select count(dateadd(dd,number,#d)) from master..spt_values
where type = 'p'
and month(dateadd(dd,number,#d))=month(#d)
and year(dateadd(dd,number,#d))=year(#d)
and cast(GETDate() as date)>= Cast(dateadd(dd,number,#JoinDate) as date )
The result of above code is 28 but I want 4
Please help me to find the expected result
This is simple date arithmetic, you do not need to use spt_values:
declare #d date = '20190225';
select datediff(month,0,#d) as MonthsDiff -- Months since an arbitrary date
,dateadd(month,datediff(month,0,#d)+1,0) as StartOfFollowingMonth -- Add months above +1 to same arbitrary date
,datediff(day,#d,dateadd(month,datediff(month,0,#d)+1,0)) as DaysBetweenGivenDate -- DATEDIFF between given date and start of month from above;
Output:
+------------+-------------------------+----------------------+
| MonthsDiff | StartOfFollowingMonth | DaysBetweenGivenDate |
+------------+-------------------------+----------------------+
| 1429 | 2019-03-01 00:00:00.000 | 4 |
+------------+-------------------------+----------------------+
Try this:
declare #date date='20140603'
select datediff(day, #date, dateadd(month, 1, #date))-day(#date)
Starting with SQL Server 2012, you could just use the EOMONTH function:
SELECT DATEDIFF(DAY, '20190225', EOMONTH ('20190225')) + 1 [thedays]
= 4.

To get the previous month's last date till last second

I want to get last month's last date (whether 30 or 31) and time till last second, whenever the query is executed.
Eg. 11/30/2015 11:59:59 PM
So I have a query like
SELECT DATEADD(ss, (60*60*24)-1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), -1))
It solves my problem. But what is the difference between the query written above and the one below, when I change the DATEDIFF part and replace 0 with 1?
SELECT DATEADD(ss, (60*60*24)-1, DATEADD(MONTH, DATEDIFF(MONTH, 1, GETDATE()), -1))
Will both of these queries gives the same result whenever they are run, or which should I consider as the permanent solution?
Do NOT do this; attempt to get the "last second" of the last day of the previous month
I make this bold statement on the assumption you are attempting to use BETWEEN and you are concerned with the accuracy of something like this:
select sum(value) from Atable
where [Adate] BETWEEN '20151201' AND '21051231 23:59:59'
But the complexity of arriving at the last point in time on the last day of any month is solved so easily by using the first day of the next month instead. All that you also need to do is drop the use of BETWEEN. Like this:
select sum(value) from Atable
where [Adate] >= '20151201' and [Adate] < '21060101'
LESS THAN "the first day of the this month"
That is how you solve your conundrum.
& by the way: The precision (accuracy) of smalldatetime, datetime and datetime2 all differ, all the more reason not to use BETWEEN.
see "Be careful about rounding errors." at http://sqlmag.com/t-sql/t-sql-best-practices-part-2
Specifically, do this:
DateLogged < SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
This will be 100% accurate for date, smalldatetime, datetime and datetime2 columns.
Here is another attempt to explain why LESS THAN [the_next_day_at_00:00:00+0000000] is accurate and using 22:59:59 is NOT accurate. Please take note of the sample data accuracy
SQL Fiddle
MS SQL Server 2014 Schema Setup:
Query 1:
DECLARE #Tbl TABLE
( [ID] int identity(1,1)
, [DT_a] datetime
, [DT_b] datetime
, [DT_c] datetime2
)
INSERT INTO #Tbl
([Dt_a], [Dt_b], [Dt_c])
VALUES
(
'20151231 23:59:59'
, '20151231 23:59:59.997'
, '20151231 23:59:59.9999999'
)
select
'where [DT_b] <= 20151231 23:59:59' as FilterString
, max([Dt_a]) as [Dt_a]
, max([Dt_b]) as [Dt_b]
, max([Dt_c]) as [Dt_c]
from #Tbl
where [DT_b] <= '20151231 23:59:59'
UNION ALL
select
'where [DT_b] < 20160101'
, max([Dt_a]) as [Dt_a]
, max([Dt_b]) as [Dt_b]
, max([Dt_c]) as [Dt_c]
from #Tbl
where [DT_b] < '20160101'
Results:
| FilterString | Dt_a | Dt_b | Dt_c |
|-----------------------------------|----------------------------|----------------------------|-----------------------------|
| where [DT_b] <= 20151231 23:59:59 | (null) | (null) | (null) |
| where [DT_b] < 20160101 | December, 31 2015 23:59:59 | December, 31 2015 23:59:59 | 2015-12-31 23:59:59.9999999 |
Data accuracy
smalldatetime: one minute
datetime: rounded to increments of .000, .003, or .007 seconds
datetime2: 100 nanoseconds
To avoid possible errors from rounding by time units DO NOT USE <= 23:59:59
Instead use LESS THAN [the_next_day]
AND, as a consequence AVOID USING BETWEEN for date ranges.
See this link for how DATEDIFF is used or should be used in SQL Server. The 2nd argument, the one which does not seem to make a difference in your case, is supposed to be the start date which is subtracted from the end date (getdate()) to get the difference and then converted to months. I would try and use this function the typical way and provide a proper start date.
Also below is an alternative way of getting the same result
SELECT DATEADD(ss, -1, '01/' + CONVERT(VARCHAR, DATEPART(MONTH, getdate())) + '/' + CONVERT(VARCHAR, DATEPART(YEAR, getdate())));
It is because of DATEDIFF( MONTH, 0, GETDATE()) Function
If you use an integer as the second argument, this is interpreted as the number of days since 1900-01-01 regardless of the Interval you are using in the datediff function.
For eg:
SELECT YEAR(0), MONTH(0), DAY(0);
year month day
1900 1 1
Now if I Increment 0 to 1 in year, month, day
SELECT YEAR(1), MONTH(1), DAY(1);
year month day
1900 1 2
Now if I Increment values to 365,
SELECT YEAR(365), MONTH(365), DAY(365);
year month day
1901 1 1
You can see the Year got incremented by 1.
there are many ways to find out the previous month's last date. Here is the one I am using.
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
Well it would be expected that substracting one millisecond to the first day of the current month you would get the last millisecond of the previous month but it doesn't work that whay, with datediff millisecond,-1 you still get the first day of the month you have to do datediff millisecond,-2 to reach 997 milliseconds, no way to get 999 nor 998.(without using text).
select dateadd(MILLISECOND,-2,dateadd(month, datediff(month, 0, getdate()), 0))
And you get 2020-01-31 23:59:59.997
To get last second of current month use:
SELECT DATEADD(MILLISECOND, -10, CAST (EOMONTH(GETDATE()) AS DATETIME))
and you get:
2021-12-30 23:59:59.000
Explanation: takes begin of next month (2021-12-31) and convert to datetime (2021-12-31 00:00:00.000) then takes 1 second to get (2021-12-30 23:59:59.000)

converting multiple date formats to date in sql server

I have requirement to convert multiple date types input entered by users to standard date format i.e
Input Date Format from old table is of Varchar data type and can be either of DD/MM/YYYY or DDMMYYYY or DDMMYY formats (manually entered by users)
Example: 08/10/2013 or 08102013 or 081013
And my requirement is to convert this to standard date format, how can I achieve this ?
Any help would be appreciated
SQL Fiddle
MS SQL Server 2008 Schema Setup:
create table YourTable(DateCol varchar(20))
insert into YourTable values ('08/10/2013'), ('08102013'), ('081013')
Query 1:
select
case len(DateCol)
when 10 then convert(date, DateCol, 103)
when 8 then convert(date, stuff(stuff(DateCol, 5, 0, '/'), 3, 0, '/'), 103)
when 6 then convert(date, stuff(stuff(DateCol, 5, 0, '/'), 3, 0, '/'), 3)
end
from YourTable
Results:
| COLUMN_0 |
|------------|
| 2013-10-08 |
| 2013-10-08 |
| 2013-10-08 |

Resources