Error converting string, '2015-08-23', to date - sql-server

I am trying to clean my data prior to loading into PowerBI to create the visuals. I have created my query as:
CREATE VIEW Project2 AS (
Select
p.playerID as ID1,
p.birthYear,
p.birthMonth,
p.birthDay,
p.birthCity,
p.deathYear,
p.nameFirst,
p.nameLast,
p.nameGiven,
p.weight,
p.bats,
p.throws,
p.finalGame,
b.*
from dbo.People as p
LEFT JOIN dbo.Batting as b
ON p.playerID=b.playerID
and b.G >= 50
WHERE (p.finalGame is null or p.finalGame >= 2018));
This works great until attempting to load the view into PowerBI I get this error:
DataSource.Error: Microsoft SQL: Conversion failed when converting the varchar value '2015-08-23' to data type int.
Details:
DataSourceKind=SQL
DataSourcePath=laptop-o4rhi9q7;Baseball
Message=Conversion failed when converting the varchar value '2015-08-23' to data type int.
ErrorCode=-2146232060
Number=245
Class=16
I can't figure out where /how to utilize cast(p.finalGame as date) in correct syntax, any ideas?

You must use a proper date literal for this, which means it must be enclosed in quotes, and ideally use a non-ambiguous format
WHERE (p.finalGame is null or p.finalGame >= '20180101'));
If finalGame is actuall varchar you would need to convert it using an appropriate conversion type. For example
WHERE (p.finalGame is null or CONVERT(date, p.finalGame, 102) >= '20180101'));
That may not be the correct format number, the full list is here.
I urge you to change the column type to date in the first place.

If the data for p.finalGame = '2015-08-23', you'll need to cast that as a date in your WHERE clause.
CREATE VIEW Project2 AS (
Select
p.playerID as ID1,
p.birthYear,
p.birthMonth,
p.birthDay,
p.birthCity,
p.deathYear,
p.nameFirst,
p.nameLast,
p.nameGiven,
p.weight,
p.bats,
p.throws,
p.finalGame,
b.*
from dbo.People as p
LEFT JOIN dbo.Batting as b
ON p.playerID=b.playerID
and b.G >= 50
WHERE (p.finalGame is null or cast(p.finalGame as DATE) >= 2018));

Based on the error message, you date appears to be a string of the form 'yyyy-mm-dd', not a true date type or an integer year. I believe your fix is to quote your year. Either
WHERE (p.finalGame is null or p.finalGame >= '2018');
or
WHERE (p.finalGame is null or p.finalGame >= '2018-01-01');
If your year is a variable, convert it to a string with something like CONVERT(VARCHAR(10), #Year). (This assumes a 4 digit value.)
As already noted, a better approach (if you have the ability to change the schema) is to redefine finalGame as a true DATE or DATETIME type. Then you could compare p.finalGame >= '2018-01-01' or p.finalGame >= DATEFROMPARTS(#Year, 1, 1).

Related

How to convert a column value which is like 20220401 of number datatype to 2022-04-01 in snowflake

I have a column of number data type in snowflake that stores values like 20220401, now I need to convert it into date format. Could someone please help
You can use to_date, but it works on char datatype, so first need to convert your column to char/string.
with data_cte(col1) as
(select 20220401::number)
select to_date(col1::string,'yyyymmdd') from data_cte
select to_date('02/14/2014', 'MM/DD/YYYY');
create table number_to_date(numbers integer);
insert into number_to_date values (20220401);
select to_date(to_char(numbers),'YYYYMMDD') from number_to_date;
More details: https://docs.snowflake.com/en/sql-reference/functions/to_date.html#examples
Yet more way's of seeing/saying the same thing:
to_date allows you to define format string
select column1 as raw_str,
to_date(column1, 'yyyymmdd') as as_date
from values
('19900101'),
('20220511');
gives:
RAW_STR
AS_DATE
19900101
1990-01-01
20220511
2022-05-11
if you have string that sometimes are not following the format pattern you might want to use try_to_date as this will not generate an error:
select column1 as raw_str,
try_to_date(column1, 'yyyymmdd') as as_date
from values
('19900101'),
('not a date'),
('20220511');
RAW_STR
AS_DATE
19900101
1990-01-01
not a date
null
20220511
2022-05-11
But given you said "number input"
select column1 as raw_number,
to_date(column1::text, 'yyyymmdd') as as_date
from values
(19900101),
(20220511);
now we have numbers, but to_date wants text, so we cast it to text, so the parser can be used.
giving:
RAW_NUMBER
AS_DATE
19,900,101
1990-01-01
20,220,511
2022-05-11
Now if you use TO_TIMESTAMP which accepts the same format string, the naked number by itself it will think you mean epoch seconds, and give you wacky tiny number, like:
select column1 as raw_number,
to_timestamp(column1) as as_timestamp
from values
(19900101),
(20220511);
RAW_NUMBER
AS_TIMESTAMP
19,900,101
1970-08-19 07:48:21.000
20,220,511
1970-08-23 00:48:31.000
which is all to say, cast it to string via ::text or the likes, and specify your format, so that you can handle yyyymmdd or yyyyddmm or how every your data is.

Getting Conversion failed when converting date and/or time from character string error

Table is having the column as ret_period and contains varchar datatype. I'm trying to write the query for converting the datatype of column from varchar to date datatype .but it is throwing an error as Conversion failed when converting date and/or time from character string.
Can any one please let me know how to resolve this issue!
below is the sample data of column.
ret_period
012018
012019
012020
You could transform the string to a format that can be converted/casted to a DATE.
select *
, TRY_CAST(CONCAT(RIGHT(ret_period, 4),'-',LEFT(ret_period, 2),'-01') AS DATE) AS ret_date
from (values
('012018'),
('012019'),
('012020')
) q(ret_period)
Note however, that the yyyyMMDD format should be a safer than yyyy-MM-DD, since it doesn't depend on the language when casting it to a DATETIME.
Or use the DATEFROMPARTS function
select *
, DATEFROMPARTS(RIGHT(ret_period, 4), LEFT(ret_period, 2), 1) AS ret_date
from (values
('012018'),
('012019'),
('012020')
) q(ret_period)
ret_period
ret_date
012018
2018-01-01
012019
2019-01-01
012020
2020-01-01

Can i use a case statement to convert a varchar to decimal and use that in my where clause?

I have a column which I want to convert to decimal so I can then use it to compare in my where clause. I want to make sure all values from the column are greater or equal to 1.3. I converted the column successfully in the select statement but when attempting to do the same convert in the where clause I get the following error:
Arithmetic overflow error converting varchar to data type numeric.
I am using SQL Server 2008.
SELECT ID,
CASE
WHEN ISNUMERIC(USER_3) = 1
THEN Convert(varchar(50), CONVERT(decimal(14,2), USER_3))
END AS KG_M
FROM PART
WHERE USER_3 IS NOT NULL
AND CASE
WHEN ISNUMERIC(USER_3) = 1
THEN Convert(varchar(50), CONVERT(decimal(14,2), USER_3))
END >= 1.3
Sure, why not? Here's a self-contained example:
select a.ID
, b.KG_M
from (values
(1, N'12345678')
, (2, N'ABCDEFGH')
) as a (ID, USER_3)
cross apply (values(
case IsNumeric(a.USER_3)
when 1 then Convert(varchar(50), Convert(decimal(14, 2), a.USER_3))
else a.USER_3
end
)) as b (KG_M)
where b.KG_M >= '1.3';
We simply use the APPLY operator to contain our calculation for reuse later.
You need to choose one way to convert. I would use the native type for comparison, decimal.
SELECT * FROM
(
SELECT ID, KG_M=CAST(USER_3 AS decimal(14,2))
FROM PART
WHERE
ISNUMERIC(USER_3) = 1
)AS X
WHERE
X.KG_M >= 1.3
Allow strings that are not numbers in outoput
SELECT * FROM
(
SELECT
ID,
USER_3_AsDecimal=CASE WHEN ISNUMERIC(USER_3) THEN CAST(USER_3 AS decimal(14,2)) ELSE NULL END,
USER_3
FROM PART
WHERE
NOT USER_3 IS NULL
)AS X
WHERE
X.USER_3_AsDecimal IS NULL
OR
X.USER_3_AsDecimal >= 1.3
The problem was a syntax error, the case in the where clause was a success the entire time.
"you should use >= '1.3' since you are converting to varchar" credit to #Lamak in comments

Query using a date range but end date may be null

sql server 2014
I am trying to query data using a date range. Data in the table is datetime datatype.
so I want to use as parameters #IncidentDate and #IncidentEndDate.
Issues are that the #IncidentEndDate may be null. Also each row in the data may or may not have an end_datetime (null if no date)
In my where clause I have
(end_datetime IS NULL) AND (#IncidentDate >= CAST(start_datetime AS DATE) AND #IncidentDate <= DATEADD(d,0,DATEDIFF(d,0,start_datetime)))
OR
(#IncidentDate <= end_datetime) AND (#IncidentEndDate >= start_datetime)
However I am not sure if this si working properly. I would expect rows that have no end_datetime to appear in the results but they don't seem to be .
EDIT: In the end I came up with the following after reading everybody's replies...
WHERE (
#IncidentDate <= isnull(end_datetime, dateadd(day,1,start_datetime))
)
AND (
isnull(#IncidentEndDate,dateadd(day,1,#IncidentDate)) >= start_datetime
)
This seems to me to be a tidier way to satisfy my requirements - it looks after the possiblity of both end_datetime being null and #IncdidentEndDate being Null
Also, you can use the ISNULL() function to help handle NULL values. The ISNULL() function checks the value and, if it's NULL, replaces it with a supplied value. So if you wanted the NULLs, you could put in a value that would match or, if not, something that would definitely be outside your range like 01/01/1900 or the MIN Date (varies depending on DATETIME or DATETIME2).
To exclude:
SELECT * FROM mySweetTable WHERE ISNULL(createdDate, '01-JAN-1900') >= '01-JAN-2015'
To include:
SELECT * FROM mySweetTable WHERE ISNULL(createdDate, GETDATE()) >= '01-JAN-2015'
Although, I don't recommend ACTUALLY leaving GETDATE() in the WHERE clause, that's bad news bears; replace it with a variable or specific value.
--This should get you what you want
start_datetime >= #IncidentDate and (#IncidentEndDate is null or end_datetime is null or end_datetime < dateadd(day,1,#IncidentEndDate))
Unless, of course, you want to exclude ones where the end_datetime is null and if that's the case just let me know!

Different results between date and Cast As Date

I'm new to the T-SQl world and this issue is puzzling me.
I'm running a query against a variable I have created which holds the date of the start of my financial year, which is 2014-04-01. The data I'm querying against holds the date as a date time field, so I have been using CAST AS DATE to remove the timestamp.
If I run this query in this fashion I receive 25 results:
select count(B.WorkOrderNumber) as AWOCount
from TSP1_Dev.AssetDataPortal.EllipseSiteList A left outer join
TSP1_Dev.AssetDataPortal.tblWorkOrdersActive B
on A.EquipmentLocation = B.EquipmentLocation
where
B.EquipmentLocation = 'BISHT'
and A.EquipmentClass = 'SW'
and right(rtrim(A.EquipmentDesc),4) = '(OU)'
and cast(B.CreationDate as Date) >= '2014-04-01';
However, on one occasion I forgot to cast the date, and when I did that I received 32 results:
select count(B.WorkOrderNumber) as AWOCount
from TSP1_Dev.AssetDataPortal.EllipseSiteList A left outer join
TSP1_Dev.AssetDataPortal.tblWorkOrdersActive B
on A.EquipmentLocation = B.EquipmentLocation
where
B.EquipmentLocation = 'BISHT'
and A.EquipmentClass = 'SW'
and right(rtrim(A.EquipmentDesc),4) = '(OU)'
and B.CreationDate >= '2014-04-01';
Can someone please tell me why? Apologies for my ignorance!
Neil
In the query you have string literals and from your comment I can only assume that it is Coldfusion that insert the string literal in your query. (I know nothing about Coldfusion but is there no way to use parameters instead?).
In SQL Server there is a setting for the order of date parts in strings. SET DATEFORMAT
What you see can be reproduced if you have the date format dmy.
The string literal 2014-04-01 is interpreted as yyyy-dd-mm when compared against a datetime. When the new data types date and datetime2 was added that behaviour was changed so string literal on the form yyyy-mm-dd will always be interpreted as just that regardless of set dateformat.
So when you cast to date the string literal is converted to the date 2014-04-01 but when you compare against a datetime the string literal is converted to 2014-01-04.
set dateformat dmy;
declare #T table(D datetime);
insert into #T(D) values
('20140101'),('20140201'),
('20140301'),('20140401'),
('20140501'),('20140601');
select count(*)
from #T
where D >= '2014-04-01';
select count(*)
from #T
where cast(D as date) >= '2014-04-01';
Result:
5
3
One way to avoid the problem for datetime is to use a string literal without dashes. 20140401 will be interpreted as yyyymmdd regardless of set dateformat.

Resources