Concatenate 2 x fields to make a Date - sql-server

I have 2 x fields T1.period and T1.year both have data type smallint
Using SQL Management Studio 2014 how may I Concatenate them AND return result as a DATE type?
Also, T1.period has values 1 to 12 how may I pad this out to 01 to 12 ... or will changing to date type sort this out?
Much appreciated!
Sample data ...
period yr
1 2015
2 2009
12 2009
11 2010
10 2011
Result will be ...
Date
01/01/2015
01/02/2009
01/12/2009
01/11/2010
01/10/2011
Thanks!
Looks terrible struggling to get it into lists - sorry :(

Converting Your Values The Old Fashioned Way
Assuming that your t1.period value actually just represents a month, you could consider just converting your values to strings and then converting that concatenated result into a date via the CAST() function :
SELECT CAST(CAST(t1.year AS VARCHAR) + '-' + CAST(t1.period AS VARCHAR) + '-1' AS DATE)
This will build a string that looks like {year}-{month}-1, which will then be parsed as a DATE and should give you the first date of the given month/year.
Using The DATEFROMPARTS() Function
SQL Server 2012 and above actually support a DATEFROMPARTS() function that will allow you to pass in the various parts (year, month, day) to build a corresponding DATE object, with a much easier to read syntax :
SELECT DATEFROMPARTS(t1.year,t1.period,1)
Additionally, if you needed a DATETIME object, you could use DATETIMEFROMPARTS() as expected.

Related

Convert Wed Oct 14 08:00:00 CDT 2020 format to DateOnly and Time Only

We receive a csv file that has a column in this date format -- Wed Oct 14 08:00:00 CDT 2020, along with a column that has a count for each date/time
I am using an SSIS package to grab the file and import this data into a sql table, then I can format it the way I need to and then actually export the data in the format needed.
If there is a way to do this all within one SSIS package I am all ears but currently I am working on just getting the data into SQL and converted to the right format so that I can export it.
I need to get that file and convert that date format and split it up into two separate columns
One column will be just the date in this format 2020-10-14 00:00:00.000
One column will be just the time in this format 08:00:00.0000000
Updated to change the dates to match so it's not as confusing and also the error I am receiving when running the suggested code below.
Image of Error I'm recieving
Image of table with the data I am trying to convert
Image of table attributes
Screenshot of my screen when running a select * from the table I am pulling the data that I need converted
Screenshot of the error I receive when running the query by Aaron.
If this is the format it will always be in, and timezone is irrelevant, you can first try to convert it to a datetime, then you can extract the parts from that.
SET LANGUAGE us_english; -- important because not all languages understand "Oct"
;WITH src AS
(
SELECT dt = TRY_CONVERT(datetime, RIGHT(OpenedDateTime ,4)
+ SUBSTRING(OpenedDatetime, 4, 16))
--, other columns...
FROM [dbo].[VIRTUALROSTERIMPORT_Res_Import]
)
SELECT OpenedDateTime = CONVERT(datetime, CONVERT(date, dt)),
OnHour = CONVERT(time, dt)
--, other columns...
FROM src;
Results:
OpenedDateTime OnHour
-------------- ----------------
2020-10-14 08:00:00.0000000
If you need to shift from one timezone to another timezone, that's a different problem.
I was just showing the date formats, don't look so into the actual date examples I used. The time zone is irrelevant I just need the formats changed.
When I used The code Aaron suggested I got a conversion error: I'm assuming its because the columns are varchar in the table, but I cant get the dates to load as date formats bc SSIS keeps giving me truncated errors-- so I have to load it as varchar.
Below is the code I was running, I tweaked it to use the column and table names I am using.
SET LANGUAGE us_english; -- important because not all languages understand "Oct"
DECLARE #foo varchar(36) = 'Wed Oct 14 08:00:00 CDT 2020';
;WITH src(d) AS
(
SELECT TRY_CONVERT(datetime, RIGHT(#foo,4) + SUBSTRING(#foo, 4, 16))
)
SELECT OpenedDateTime = CONVERT(datetime, CONVERT(date, OpenedDateTime)),
onhour = CONVERT(time, OpenedDateTime)
FROM [dbo].[VIRTUALROSTERIMPORT_Res_Import];

How to use - within like '%'% query

I have a table column in SQL 2012 called transitiontime that contains dates and times in the format 2017-02-02 21:00:34.847. I'm trying to query all results within the last 3 months, which I would think would just require me to look for 2017-02, or something to that effect. However if I leave the hyphen in, the query fails.
Examples:
WHERE transitiontime like '%2017%' <- works but returns all values from this year
WHERE transitiontime like '%2017-02%' <- Does not work at all
WHERE transitiontime like '%2017%02%' <- Works but pulls in anything with 2017 and 02 in it, even if 02 is just in the time.
I would love to get the past 3 months in one query, but right now I'd like to just be able to pull from 1 month.
I'm assuming, since you are using the keyword "like", that the field "transitiontime" is a char oder varchar field?
Change the type of the field to DateTime and use the following query, to get all results for the last three months (applying to SQL):
SELECT * FROM table WHERE transitiontime >= DATEADD(month, -3, GETDATE())

SQL Server compare datetime fields

I have a datetime field in my table that I need to use in a where clause.
The fieldname is DatumAanname
In my dataviewgrid it shows for example "16/12/2014 15:57:04"
I looked at the page from microsoft with all the datetime options for a convert, but this format does not seems to be on that page.
The closest format I can see there is "16 12 2014 15:57:04" which should be 113
I tried a query like this
SELECT o.DatumAanname,
(convert(DATETIME, '16 dec 2014 15:57:04:000', 113)),
(convert(DATETIME, '16 dec 2014 15:57:04', 113)),
(convert(DATETIME, o.DatumAanname, 113))
FROM vwOpdracht o
this returns 4 fields which all look exact the same
but when I do
where (convert(datetime, o.DatumAanname, 113)) = (convert(datetime, '16 dec 2014 15:57:04:000', 113))
it returns 0 records
What am I doing wrong here ?
Dates have no formats, they are native types with their own binary storage. Formats and conversions apply only when converting from/to string and they frequently cause problems if incompatible collations and cultures are used.
The best way to avoid problems is simply to remove strings entirely: use date-typed columns in the table and query using parameterized queries. Actually, if the date is stored as text in the table there is no generic and fault-proof way to acoid problems.
Pass strongly typed values instead of strings (eg DateTime in C#, date, datetime,datetime2 in T-SQL). For example:
where o.DatumAanname= #dateParam
will return matching entries if the values match.
If passing date parameters isn't possible, you should only use the unambiguous ISO8691 format, eg:
where o.DatumAanname = '2014-12-16T15:57:04'
If you want to pass date-only values you can use the unseparated format which is also unambiguous
where o.DatumAanname = '20141216'
One thing to note is that date values must match exactly, down to the millisecond. Typically dates are used in range queries where this isn't an issue. In equality queries though, this can be a problem.
You can avoid this by using datetime2(0) as the field type, which ensures that milliseconds aren't stored at all.
Another option is to use a range instead of an equality query, eg:
where o.DatumAanname between '2014-12-16T15:57:04' and '2014-12-16T15:57:04.999'
or
where o.DatumAanname between '2014-12-16T15:57:00' and '2014-12-16T15:57:59'
if you want minute-level precision

Excel incorrectly converts Date into Int

I'm pulling the data from SQL database. I have a couple columns with date which need to be converted into Int type, but when I do this the date changes (-2 days). I tried Cast and Convert and it's always the same.
Converting to other type works fine and returns the correct date, but doesn't work for me. I need only the date part from datetime and it needs to be recognised as a date by Excel.
Why is this happening? Any ideas how to get it sorted?
I'm using the following query:
SELECT wotype3, CONVERT(INT,wo_date2 ,103), CAST(duedate AS int) FROM Tasks WHERE
duedate > DATEADD(DAY,1, GETDATE())
AND wo_date2>0
AND wo_date2<DATEADD(WEEK,3,GETDATE())
ORDER BY wotype3
I've had big problems with this, checking my SQL Server's calculation results with "expected results" which a user had created using Excel.
We had discrepancies just because of this 2-day date difference.
Why does it happen ?
Two reasons:
SQL Server uses a zero-based date count from Jan 1 1900, but Excel uses a 1-based date count from Jan 1 1900.
Excel has a bug in it (gasp!) which makes it think that the year 1900 was a leap year. It wasn't. SQL Server correctly refuses to let you have a date value containing "29-Feb-1900".
Combine these two discrepancies, and this is why all dates, from March 1 1900 onwards, are always 2-days out.
Apparently, this Excel bug is a known issue, to keep it in line with Lotus 1-2-3.
The Intentional Date Bug
Microsoft's own explanation
From now on, I think I'll justify bugs in my code with the same excuse.
;-)
For SQL Server 2008 and above, you can use the DATE datatype.
declare #dt datetime = '12/24/2013 10:45 PM' -- some date for example
SELECT #dt as OriginalDateTime, CAST(#dt as DATE) as OnlyDate
For versions prior to SQL Server 2008, you would need to truncate the time part using one or the other functions. Here is one way to do that:
declare #dt datetime = '12/24/2013 10:45 PM' -- some date for example
SELECT #dt as OriginalDateTime, CAST(FLOOR(CAST(#dt AS FLOAT)) as DATETIME) as OnlyDate

SQL Server date calculations in stored procedures

I wanted to ask 3 questions about below code (please excuse the long code listing, I am including these lines in the hopes that it provides enough context).
Note that the code here depends on the date when it is executed. For this reason my questions refer to a hypothetical situation with two different execution dates:
March 1st 2014
January 1st 2014
My questions are on whether my understanding on some parts of this is correct, i.e:
A. that the SELECT DATEADD expression (on line 1) would:
On March 1st 2014 create the datetime 2014-02-31 23:59:59
B. that the code on lines 6-9 would:
On March 1st 2014 create the datetime 2014-02-01 00:00:00
On January 1st 2014 create the datetime 2013-02-01 00:00:00
and
C. that the code on lines 11-14 would:
On March 1st 2014 create the datetime 2015-01-30 00:00:00
On January 1st 2014 create the datetime 2014-01-30 00:00:00
Is this understanding correct?
1. SET #ldpmth = (SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) )
2. SET #yr = (SELECT YEAR(#ldpmth))
3. SET #mth = 0
4. SET #dy = 0
5.
6. SET #fysdate = (SELECT CASE WHEN MONTH(#ldpmth) >= 2 THEN
7. DATEADD(MM, 1,CAST(CAST(#yr+#mth+#dy AS NVARCHAR(50)) AS DATETIME))
8. ELSE DATEADD(MM, 1, CAST(CAST((#yr-1)+#mth+#dy AS NVARCHAR(50))
9. AS DATETIME)) END )
10.
11. SET #fyedate = (SELECT CASE WHEN MONTH(#ldpmth) >= 2 THEN
12. DATEADD(YY, 1, CAST(CAST(#yr+#mth+#dy AS NVARCHAR(50)) AS DATETIME)) + 30
13. ELSE DATEADD(YY, 1, CAST(CAST((#yr-1)+#mth+#dy AS NVARCHAR(50))
14. AS DATETIME)) + 30 END )
(Thank you for all who answered so far. This is actually code that was developed (but not documented) at my place of employment some years ago and I have been tasked with converting it to a form that works client-side with Crystal Reports.)
On March 1st 2014 create the datetime 2014-02-31 23:59:59
No. AFAIK, there isn't any dbms that's so dumb it thinks Feb 31 is an actual date. The SQL statement on line 1 will return the value 'Feb 28 2014 23:59:59'.
You can test all your statements by substituting actual dates for GETDATE() and guesswork. In the first query, for example, use
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,'2014-03-01'),0));
^^^^^^^^^^
You can probably run a version of SQL Server locally. SQL Server 2008 even installs on Windows XP. If you can't bear that, though, there's always sqlfiddle.com.
This could be easily tested in SQL Server Management Studio (SSMS). I'll answer the first, and you can test the next two yourself.
Question:
A. that the DATEADD (on line 1) would on March 1st 2014 create the datetime 2014-02-31 23:59:59
Answer: No, because February can't possibly have 31 days, so it can't return '2014-02-31`
Proof:
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,'2014-03-01'),0))
Results
(No column name)
2014-02-28 23:59:59.000
For (B) and (C), if you'd stated your question, instead, as "My financial years run from 1st February until 30th(sic) January - how do I get the start and end dates for the current financial year, I'd have offered:
SET #fysdate = DATEADD(year,DATEDIFF(month,'19000201',GETDATE())/12,'19000201')
and:
SET #fyedate = DATEADD(year,DATEDIFF(month,'19000201',GETDATE())/12,'19010131')
(Note that this second finds the 31st Jan, not the 30th. I assume that was carelessness in your original question).
But, as to (A), as I indicated, I thought your question is again poorly phrased - if you're trying to find the end point of a period and that period is defined on datetimes (as opposed to just dates), it's far easier to construct an exclusive upper bound:
SET #ldpmth = DATEADD(month, DATEDIFF(month,0,GETDATE()),0)
This bound (to be used with a < comparison rather than <= or BETWEEN) doesn't artificially exclude any values with a time such as 23:59:59.527. Note also, that if the financial year end date calculation is going to be used against datetime values which include times, I'd again counsel computing an exclusive upper bound, and substitute 19010201 instead of 19010131.
So, in total, I don't think I've actually answered your questions as posed, but I think I've provided the answers you should have been seeking.

Resources