Date cast to int - why is it wrong? - sql

I've got a question. Why does date CAST to int doesn't work while varchar to int works fine? e.g.
If we declare a variable and run this query it won't work,
declare #dateb datetime
set #dateb = getdate()
select cast(#dateb as int)
while this query will work fine. Why?
select cast(convert(varchar(8),#dateb,112) as int)
date should be 8 numbers.

Your issue comes from a misunderstanding about how SQL Server stores date information. It isn't stored as a readable date, but rather as an integer, or series of integers, that the engine uses to calculate the date in question, and then display in a human friendly way.
The CONVERT function you used above creates a text representation of the date as you're expecting to see it, then converts that representation to an integer (also as you're expecting to see it). The straight conversion from a date data type shows you the integer that SQL Server actually uses to store "today", but that's not what you're expecting.
There's a really good article about it on Robert Sheldon's blog if you're interested in going into more depth.

Related

Hive converting int column to string and to the target type: date

I have a problem with conversion of datatypes in hiveql. Data type of a column is int, it should be converted to date, but there is no direct conversion function from int to date. At first I converted int into string and it worked as below:
From this moment I based on the second column where I have my data converted to string. When I try to use cast(string as date), then the third column returns only nulls:
What is interesting, there is no problem when the string value to be converted was typed manually by a user:
Does anyone of You know how to deal with this problem?
your method in the comment is quite good.
One more approach using regexp_replace:
select date(regexp_replace(cda_date,'^(\\d{4})(\\d{2})(\\d{2})','$1-$2-$3'))

Converting from mmddyyyy to yyyymmdd with SQL

I should preface my question by saying I am very new to SQL (or any programming involving databases). I started learning SQL a couple of weeks ago when I decided to take on a data project.
I have been using SSMS in wrangling large tables in comma-separated text file format. I need to be able to sort by dates, and the current format is mmddyyyy, but when I try to sort by date it does not work.
I know that converting dates is something that gets asked a lot around here, but I haven't found any solutions that explain things for a newb like myself.
So far my guesses for a solution are to use the CONVERT or CAST solutions, but I'm not sure if that is the right approach. I have found several CAST/CONVERT posts but none have really applied to my situation.
I hate to have this as my first question, but I'd thought I'd take some down vote bullets if it means I could figure this out. Thank you.
Sample of what I'm trying to do:
SELECT *
FROM [databasename].[dbo].[table1]
WHERE [ column1] > 01012017;
I get the entire table back, unsorted.
Since your:
SELECT *
FROM [databasename].[dbo].[table1]
WHERE [ column1] > 01012017;
does not error, we could say that the [column1]'s datatype is either a character type (like VARCHAR, char), or datetime.
Since you are getting back all the data and I would think you don't have data in the future, it should be a varchar (or char) - with datetime that means 1900-01-01 + 1012017 days.
To make it a datetime you need to 'cast' your column1 which is in mmddyyyy form by first converting it to yyyymmdd style (which would work under any date and language setting):
cast(right([column1],4)+substring([column1],1,2)+substring([column1],3,2) as datetime)
and you would write that 01012017 as a string (quotes around) and also again in yyyymmdd format (it would be implicitly casted to datetime):
'20170101'
So your SQL becomes:
SELECT *
FROM [databasename].[dbo].[table1]
WHERE cast(right([column1],4) +
substring([column1],1,2) +
substring([column1],3,2) as datetime) > '20170101';
Having a date\datetime column as varchar and using like this would render the ability to use simple indexes but that is another matter. For now, this would return the data you want.
Assuming your column's datatype is [Date], try something similar to:
SELECT *
FROM [databasename].[dbo].[table1]
WHERE FORMAT([column1],'dd/MM/yyyy') >'01012017'
If it's string format, you'll have to use CONVERT() to convert the column to Date with a query like
SELECT *
FROM [databasename].[dbo].[table1]
WHERE CONVERT(NVARCHAR(10), [Column1], 112) >'01012017'
Refer to this W3Schools article if you need more help with the CONVERT clause

Why does LEFT(Datetime,1) give me "J"?

So I'm writing a SQL query and it gives me an odd error:
Conversion failed when converting the varchar value 'J' to data type int
I narrowed it down to a LEFT(ProjApprovelDate,1), which for some reason gives me a J.
ProjApprovelDate is a DateTime most of the time, there are a few instances where it is entered incorrectly and is an int instead. To find these I've used (LEFT(ap.ApprovalDate,1) != 1 and LEFT(ap.ApprovalDate,1) != 2). It always begins with either a 1 or 2 when it's in the wrong format. The whole column (in the original table) is int format and shows up with most dates like 20170614, but there are several that show up like 1170614 instead. I'm converting these into the correct format and inserting them all into a new table with this column as DateTime so that it correctly makes them into a date.
When reviewing to make sure that I got them all I found this interesting case where the ones that are already formatted correctly as DateTime give me a J.
So my question is why does taking the first LEFT character of a DateTime give a J for the output?
The implicit conversion is a string, so...
Select cast(getdate() as varchar(25))
,left(getdate(),1)
Returns
(No column name) (No column name)
Jun 14 2017 10:28AM J
Take a peek at https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-type-conversion-database-engine
Just for fun, try
Select left(25,1)

SQL-Server Time data type

From what i've read so far, the data type time in sql server (starting with 2008) should be able to store the time in a HH:MM format. Then I tried this myself with the following simple exercise:
create table #mytable (id int, lat float, lon float, trajectory_id int, theTime time(5))
insert into #mytable values
('1','15.8','17.1','162','10:01'),
('2','11.5','59.7','162','10:02'),
('3','16.4','79.9','162','10:03'),
('4','29.5','10.3','180','11:12'),
('5','58.2','11.1','180','11:13'),
('6','54.5','14.1','180','11:14'),
('7','14.9','15.2','166','13:40'),
('8','15.0','13.1','166','13:42')
My expected result for the column theTime was:
theTime
10:01
10:02
10:03
11:12
11:13
11:14
13:40
13:42
What I got instead was:
theTime
10:01:00.00000
10:02:00.00000
10:03:00.00000
11:12:00.00000
11:13:00.00000
11:14:00.00000
13:40:00.00000
13:42:00.00000
Sure, I could select left(theTime, 5) and get the expected result. But i'm wondering how I could insert it directly in the desired format.
I want to use a built in function and not to store the numbers in an int for HH, MM, SS as one might have used before sql server 2005.
Using sql server 2012. Thanks
You seem confused by the difference between internal formats and display formats. TIME is a data type built into the language. When it prints out, it prints out with hours, minutes, and seconds. That is how the data type prints out, in the same way the SQL Server does not put commas in integers bigger than 1000 and uses an appropriate symbol for the decimal place. (Or for that matter prints out integers in base 10 rather than the binary format as they are actually stored.)
When you say TIME(5) you are saying that you want at least 5 decimal places of precision for fractional seconds: HH:MM:SS.SSSSS. There is no option for removing seconds altogether from the time type.
If you want to print it out in a particular format, use convert(), cast(), or format(). Happily, cast() works quite well for times. The plethora of inscrutable numeric codes for date/time are more applicable to dates, than times.
When you do left(thetime, 5) then you are implicitly converting time to a string and taking the first five characters. This seems to meet your needs. I would suggest that you just build this into your table:
alter table #mytable add thetime_hhmm as (left(thetime, 5));
Then you can use thetime_hhmm to get the value as a string with the format you want.
You can't control the format that a data type is stored as. Your time data is actually being stored as a bunch of bits -- 0's and 1's -- and it's only being displayed like 10:01:00.00000 in your query analyzer.
If you want to show it in another format, then you have to convert it to a text data type like varchar, but this is usually something your UI layer should handle, not your data layer.

DATE vs. DATETIME casting of invalid dates in SQL SERVER 2008 R2

So, while I recognize that date formatting etc. should be done in the presentation layer, I am interested to know if anyone has seen or recognized this difference (please try at home, if so inclined) I am a little baffled and mostly curious, the sample code first.
UPDATE: To clarify based on the initial responses, I am aware the date IS invalid or better "not safe", since the particular field that I am more generally concerned about comes from user input." That is, while I am aware that validation/formatting aren't SQL 2008 strong suits, it is at least curious to me that DATETIME is more forgiving and I am wondering as to cause to see how forgiving."
DECLARE #RawValue NVARCHAR(30), #Value DATETIME;
SET #RawValue = '01/20.1901'
SET #Value = CAST(#RawValue AS DATETIME)
PRINT #Value
This produces the correct result for my server settings: Jan 20 1901 12:00AM
However if the penultimate line is changed to (replacing DATETIME with DATE):
SET #Value = CAST(#RawValue AS DATE)
Msg 241, Level 16, State 1, Line 8
Conversion failed when converting date and/or time from character string.
Is there an explanation out there? To be clear it doesn't matter if I DECLARE #Value to be a DATE or DATETIME or even an NVARCHAR -- Same result. The error message seems to suggest that it is having trouble converting the date AND/OR time, why would DATETIME behave any differently?
Thanks,
It is worth mentioning that DATE and DATETIME are completely different datatypes. DATE is not simply DATETIME with the time removed. For example, CAST('17520910' AS DATE) works, while the similar conversion to DATETIME does not. For you history buffs, there was no such day in England or her colonies, the calendar skipped from September 2nd to September 14. Unlike DATETIME, DATE goes back to the year 1 without considering calendar system.
Another important difference is the lack of implicit type conversion to add a number of days directly to a date. If D is datetime, D+3 is the date three days hence. If D is DATE, then D+3 produces an error.
I am assuming that since new code for implicit conversion was created from scratch for DATE that Microsoft simply made it a tad more fastidious.
can you tried with
DECLARE #RawValue NVARCHAR(30), #Value DATE;
SET #RawValue = '01.20.1901' -- or '01/20/1901'
SET #Value = CAST(#RawValue AS DATE)
PRINT #Value
your format is incorrect
use
SET #RawValue = '01/20/1901'
or
SET #RawValue = '01.20.1901'
instead of
SET #RawValue = '01/20.1901'
The problem is in SQL Server engine for parsing the datetime and cast it to Date