SQL Server DATEPART() function - sql

Today I wrote two queries on Datepart() and get different returns below
Query #1:
Select Datepart(day,'2015-07-05')
returns '5', which I expected.
Query #2:
Select Datepart(day, 2015-07-05)
Returns '27', which is a little bit funny, and I don't understand how 27 is being returned.
The difference between these two queries is one with the date inside ' ', and the other without.
Anybody can help me out here?

2015-07-05 is just a mathematical expression which adds up to the integer 2003. (Subtracting 7 from 2015 gives 2008 then subtract 5)
2003 evaluates to '1905-06-27' when implicitly cast to datetime as casting int to datetime works the same as adding that number of days to the base date of 1 Jan 1900 (i.e. equals DATEADD(DAY, 2003,'19000101')).
So this is where the 27 comes from.
The correct way to denote date literals in SQL Server is as a string '2015-07-05' (ISO format - unambiguous for newer datetime datetypes) or '20150705' (unambiguous for legacy datatypes) or using the ODBC format { d '2015-07-05' }.

Related

LEFT Function in SQL Server returns no results

I am trying to place data corresponding to a certain month into a temp table from an SQL database.
DROP TABLE
#ComPAIR_Alliance_Table
SELECT
IMOno
,period
,[service]
,alliances
INTO
#ComPAIR_Alliance_Table
FROM
com_COMPAIR.dbo.Data_BlueWaterCapacity_US_2
WHERE
LEFT(period, 7) = '2015-03'
SELECT
*
FROM #ComPAIR_Alliance_Table
The period field is in the following format: 2015-03-29 00:00:00.000
However, my code just returns an empty temp table with the right column names but no rows (even though I know for sure rows with that date exist in my table). I have already made sure that the period column is indeed a string by using is.numeric.
Could someone please help me out with what the problem could be?
Thanks!
If it is a date/datetime/datetime2 then you can compare it with 2015-03 like:
WHERE period >= '2015-03-01'
AND preiod < DATEADD(MONTH, 1, '2015-03-01')
In case there is confusion:
The above will match all March 2015 dates such as 2015-03-31, 2015-03-31 23:59:59 and 2015-03-31 23:59:59.9999999
The above is sargable: the DATEADD part does not depend on the table rows
Guessing Period is a date. If it is, stop treating it like a varchar, it isn't one. If you want values from March 2015 then do:
WHERE period >= '20150301'
AND period < '20150401'
LEFT is doing some weird stuff, because LEFT causes an implicit cast to String from Date. You can see this question for more information, but you're getting exactly what you told SQL to get - a join on rows where the left 7 characters of period equal '2015-03' which will not happen, since you're liking comparing against something like 'Jan 01'
The LEFT function needs to implicitly convert your datetime column to a varchar value to do it's work. SQL Server is choosing the varchar format of the date based on it's internationalization settings. On my server, its Mar 29 2015 12:00AM, and LEFT yields Mar 29. That's why it's not equal to 2015-03.
You should treat your column as a datetime and then perform the comparison using a valid datetime comparison, like this :
WHERE period BETWEEN '1/1/2015' AND '1/31/2015'
the date is stored as a date type. You may want to try
where convert(varchar(20), period,121)
which would convert it to string...

SQL Server 2012 - Convert CYYMMDD date to YYYYMMDD

I have a table with just over 200,000 entries where the date is stored as CYYMMDD where C is the century (currently stored as integers). For example, December 5, 1992 would show up as 1921205 and April 25, 2016 would show up as 2160425. I need to display these results in a new table in a YYYMMDD format. So for the two examples earlier it would be 19921205 and 20160425. I have tried using
CONVERT(VARCHAR(8),[DATE], 112)
This doesn't give an error but it also doesn't do the conversion so all my dates still look the same. What am I doing wrong?
You'll need to split your numeric value as follows:
DATEFROMPARTS( 1800 + FLOOR([DATE]/10000) , FLOOR([DATE]/100)%100, [DATE]%100 )

T-SQL Dates using Convert() function?

I am bit confusing here?
declare #date1 datetime = '2016-01-21 14:10:47.183'
I want to convert '2016-01-21 14:10:47.183' To '21-01-2016'
when I tried: select convert(date,#date1,105)
I am getting: 2016-01-21
But with: select convert(varchar(10),#date1,105)
I am getting: 21-01-2016
Why I am not having same results with above code?
Why should I convert to varchar?
Thanks in advance
This is just presentation matter and should be done in application layer. If you cannot do it in application you could use FORMAT (SQL Server 2012+):
declare #date1 datetime = '2016-01-21 14:10:47.183'
SELECT FORMAT(#date1, 'dd-mm-yyyy');
LiveDemo
Why I am not having same results with above code?
select convert(date,#date1,105)
-- DATETIME -> DATE
-- vs
select convert(varchar(10),#date1,105)
-- DATETIME -> VARCHAR(10) using specific style
If you only to skip time part use SELECT CAST(#date1 AS DATE) and do not bother how it is presented. It is still DATE.
To sum up: in SQL query use DATE as date, in application display it with desired format.
The reason why is because once you put a value in a datetime column (or date or any of the other variations on date-time datatypes) in SQL Server. SQL Server ceases to think of that date as having any particular format. It translates it into numbers, and stores it that way internally.
So when you select a date from a date time column, SQL Server displays it in the default format that you have selected based on your environment/local settings.
If you want to display it in any other format, you have to first convert it to a string, because as far as SQL Server is concerned, dates don't have formats. They are just numbers. The 21st day of March is the 21st day of March, whether you write it as 3/21 or 21/3.
So when you try to convert a date to a date with a different format, SQL Server just ignores you because dates don't have formats. However, if you want to convert that date to a string, SQL Server will be happy to help you display that string in any format you like.
Hope this helps, but sounds like some further research into how SQL Server stores dates would help your understanding.

How can I combine fixed month and day with sql year function?

I want to compose a date in T-SQL with a fixed day and month (always the last day and month of the year), the year must be variable.
the day is always: 31
the month is always: 12
the year is variable, let's say 2014
The format would be like 12-31-2014 or 12-31-2015.
I have the YEAR function in mind:
select '12'+YEAR(getdate())-1
but this results in 2014+12=2026.
How can I achieve this with T-SQL?
SQL Server has the DATEFROMPARTS function for this purpose:
DECLARE #date datetime = DATEFROMPARTS( 2014, 12, 31 )
Documented here: https://msdn.microsoft.com/en-us/library/hh213228.aspx
The problem you are running into is that YEAR() returns a number so the server is adding instead of concatenating. So, if you want to do it with concatenation, you'll need to force that number back into a CHAR(), and then recast the whole concatenated mess back into a DATE (assuming you want a date type returned):
select CAST('12-31-'+CAST(YEAR(getdate())-1 AS CHAR(4)) as DATE)
That being said #Dai's answer using select DATEFROMPARTS(YEAR(getdate())-1, 12, 31) is a little bit easier on the eyes, and probably the CPU.

Conversion of INTEGER to DATETIME differs to VB6

I'm looking at some legacy VB6 code (years+years old, before my time) which runs a query against an SQL 2005 db. It supplies a date restriction in the WHERE clause - where the date is given as an integer value as a result of a CLng() on the Date in VB6.
e.g.
...
WHERE SomeDateField >= 40064
40064 is what VB6 converts today's date to (8th Sep) by doing a CLng() on it.
However, in T-SQL this integer actually converts to 10th Sep:
SELECT CAST(40064 AS DATETIME)
And so the results aren't as expected.
Anyone know what may cause this difference in conversion between VB and T-SQL?
I'm assured this always worked without problem, and obviously my suggestion is to pass dates in as dates in standard ISO format. But, need to try to find the reason behind this discrepancy starting to occur.
Seems that VB datetime starts on 30th Dec 1899:
?CDbl(#30/12/1899 03:00:01#)
0.125011574074074
whereas SQL datetime starts on 1st Jun 1900:
SELECT CAST(0 AS DATETIME)
1900-01-01 00:00:00.000
This gives two days difference which fits your results :).
'VB6
CDbl(#2009-09-08#)
40064
-- SQL:
SELECT CAST(40064 AS DATETIME)
2009-09-10 00:00:00.000
There is a similar issue between Excel and SQL server described in this thread - I imagine it is the same thing?
I think it has something to do with whether there was a 29 february 1900. I believe VB6 thinks there is, but for example JavaScript disagrees. I don't know however how SQL Server handles this; i believe that it also doesn't count feb. 29.