SQL Server, DATEDIFF error, formatting of date fields? - sql

I have an error on my datediff statement. Comment out the datediff & the 'Nothing clicked' bit works fine. I think it's related to the format of the date variables.
error message..
Msg 245, Level 16, State 1, Line 2
Conversion failed when converting the varchar value 'Nothing clicked' to data type int.
select
case
when stVs.DateLastAction is null then 'Nothing clicked'
else DATEDIFF(MI,StVs.DateSessionStarted,stVs.DateLastAction)
end as test
From Stats_VisitorSessions StVs

try:
select
case
when stVs.DateLastAction is null then 'Nothing clicked'
else CONVERT(varchar(30),DATEDIFF(MI,StVs.DateSessionStarted,stVs.DateLastAction))
-- ^^^^^^^^^^^^^^^^^^^^ ^
end as test
From Stats_VisitorSessions StVs
TSQL is having a hard time resolving if the test result set column is numeric or string.
A CASE expression can only return one datatype. It cannot return both a numeric and string data type. In the OP's case, it is deciding on a numeric data type, and then it processes more rows, and finds that it needs to be a string, and it fails. See Data type precedence.

The problem here are different datatypes in the CASE expression. Add a CAST and everything should work:
select
case
when stVs.DateLastAction is null then 'Nothing clicked'
else CAST(DATEDIFF(MI,StVs.DateSessionStarted,stVs.DateLastAction) AS varchar)
end as test
From Stats_VisitorSessions StVs
Another option would be to return NULL instead of the message and let the application handle that case.

Related

CASE statement where conditional includes an IN statement redshift

CASE
WHEN code IN ('FJS354', 'JDF334')
THEN 'Lower_form'
ELSE 0
END AS format
This returns an error in Redshift
invalid input syntax for integer: "Lower_form"
I know if I change 'Lower_form' to an integer it will work however I want this column to be a string. Is there a way to do this?
I want this column to be a string.
All branches of a case expression must return the same datatype. You are giving two literal values whose datatype is not the same (string vs integer): the database makes the decision to turn them both to integers - which is not what you want.
Rremove the ambiguity by being explicit about the datatype you want to return. That is, make this literal 0 a string:
CASE WHEN code in ('FJS354','JDF334')
THEN 'Lower_form'
ELSE '0'
END as format

CASE Logic on Text to Provide Number Results In Converting Data Type Error

This code doesn't work in a SQL Server query, is there a way around this?
CASE WHEN table1.Code = 'Food' THEN table1.Amount Else NULL END as "Fee"
I get this error:
Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.
I am assuming its because I'm searching on a text field and then grabbing a numeric field in that same table, but this seems pretty straight forward. Not sure what the problem is.
Try this:
CASE WHEN table1.Code = 'Food' THEN cast(table1.Amount as varchar(8)) Else '0' END as "Fee"
Check table1.Code data type.
table1.Code must be a Character/String not a Numeric datatype.
SELECT try_cast(Amount AS FLOAT) Fee
FROM table1
WHERE try_cast(Amount AS FLOAT) IS NULL;
You can use try_cast to check which rows are failed.

t-sql Different datatype possible in a case?

I have this query
SELECT
CASE WHEN dbo.CFE_PPHY.P77 IS NOT NULL OR dbo.CFE_PPHY.P77 <>''
THEN MONTH(dbo.CFE_PPHY.P77)
WHEN dbo.CFE_PPHY.P70 IS NOT NULL OR dbo.CFE_PPHY.P70 <>''
THEN MONTH(dbo.CFE_SERVICE_EVTS.C10_2)
ELSE COALESCE(CONVERT(VARCHAR,dbo.CFE_PPHY.P77)+
CONVERT(VARCHAR,dbo.CFE_SERVICE_EVTS.C10_2),'toto') END
AS CFELiasse_DateEffetEIRL_MM_N
FROM CFE_PPHY LEFT JOIN CFE_SERVICE_EVTS ON CFE_PPHY.colA = CFE_SERVICE_EVTS.colB
The ELSE part is giving me headaches.
The columns CFE_PPHY.P77 and CFE_SERVICE_EVTS.C10_2 have date time format. I'm turning them into varchar. Yet when I'm running the query, I have the following error
Msg 245, Level 16, State 1, Line 1 Conversion failed when converting the varchar value 'toto' to data type int.
Obviously, I cannot turn toto to an integer. Fair enough. However, from my point of view, I've converted the datetime format to a varchar format, so it should do the work.
Where am I wrong?
Thanks
You have to convert all of your case expressions to varchar. SQL is deciding to case the field as int so 'toto' is invalid. If all expressions are converted to varchar this error should be solved.
http://blog.sqlauthority.com/2010/10/08/sql-server-simple-explanation-of-data-type-precedence/
Have a closer look at your case expression: in the first and second conditional branches you're returning MONTH(... which is obviously integer.
But in third branch you're returning varchar thus SQL server tries to convert it to int according to data type of previous branches and failing to do it.
Try like this,
SELECT CASE
WHEN dbo.CFE_PPHY.P77 IS NOT NULL
OR dbo.CFE_PPHY.P77 <> ''
THEN convert(VARCHAR, MONTH(dbo.CFE_PPHY.P77))
WHEN dbo.CFE_PPHY.P70 IS NOT NULL
OR dbo.CFE_PPHY.P70 <> ''
THEN convert(VARCHAR, MONTH(dbo.CFE_SERVICE_EVTS.C10_2))
ELSE COALESCE(CONVERT(VARCHAR, dbo.CFE_PPHY.P77) + CONVERT(VARCHAR, dbo.CFE_SERVICE_EVTS.C10_2), 'toto')
END AS CFELiasse_DateEffetEIRL_MM_N
FROM CFE_PPHY
LEFT JOIN CFE_SERVICE_EVTS ON CFE_PPHY.colA = CFE_SERVICE_EVTS.colB
First, when converting to a string, always include a length (in SQL Server). The default length varies by context and may not be correct.
Second, the comparison of date/time values to '' is not necessary. This is not really valid value for a date/time -- although it does get converted to a 0 which is 1900-01-01. The NULL comparison should be sufficient. Otherwise, be explicit.
Third, string concatenation will return NULL if any of the arguments are NULL.
Fourth, table aliases make a query easier to write and to read.
As far as I can tell, your case is a bit over complicated. In the ELSE, we know that dbo.CFE_PPHY.P77 is NULL, because of the first condition. So, how about:
SELECT (CASE WHEN p.P77 IS NOT NULL
THEN CAST(MONTH(p.P77) as VARCHAR(255))
WHEN p.P70 IS NOT NULL
THEN CAST(MONTH(e.C10_2) as VARCHAR(255))
ELSE 'toto'
END) AS CFELiasse_DateEffetEIRL_MM_N
FROM CFE_PPHY p LEFT JOIN
CFE_SERVICE_EVTS e
ON p.colA = e.colB;

CAST and CASE in SQL SELECT statement

I'm trying to return a string when certain conditions are true, but the I'm running into a data type issue... LI.num_seats_pur and LI.num_seats_ret are both smallint data types...
Here's where I'm stuck:
SELECT
CASE
WHEN (LI.num_seats_ret = LI.num_seats_pur)
THEN 'RET'
ELSE (LI.num_seats_pur - LI.num_seats_ret)
END as 'Seats'
FROM T_LINEITEM LI;
I understand that 'RET' is obviously not a smallint, but every combination of CAST I use here is still causing an error. Any ideas?
When using a CASE expression, if the return values have different data types, they will be converted to the one with the higher data type precedence. And since SMALLINT has a higher precedence than VARCHAR, the return value of the ELSE part, 'RET' gets converted to SMALLINT. This will then proceed to a conversion error:
Conversion failed when converting the varchar value 'RET' to data type smallint.
In order to achieve the desired result, you need to CAST the ELSE part to VARCHAR:
SELECT
CASE
WHEN (LI.num_seats_ret = LI.num_seats_pur)
THEN 'RET'
ELSE
CAST((LI.num_seats_pur - LI.num_seats_ret) AS VARCHAR(10))
END AS 'Seats'
FROM T_LINEITEM LI;

Conditionally branching in SQL based on the type of a variable

I'm selecting a value out of a table that can either be an integer or a nvarchar. It's stored as nvarchar. I want to conditionally call a function that will convert this value if it is an integer (that is, if it can be converted into an integer), otherwise I want to select the nvarchar with no conversion.
This is hitting a SQL Server 2005 database.
select case
when T.Value (is integer) then SomeConversionFunction(T.Value)
else T.Value
end as SomeAlias
from SomeTable T
Note that it is the "(is integer)" part that I'm having trouble with. Thanks in advance.
UPDATE
Check the comment on Ian's answer. It explains the why and the what a little better. Thanks to everyone for their thoughts.
select case
when ISNUMERIC(T.Value) then T.Value
else SomeConversionFunction(T.Value)
end as SomeAlias
Also, have you considered using the sql_variant data type?
The result set can only have one type associated with it for each column, you will get an error if the first row converts to an integer and there are strings that follow:
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the nvarchar value 'word' to data type int.
try this to see:
create table testing
(
strangevalue nvarchar(10)
)
insert into testing values (1)
insert into testing values ('word')
select * from testing
select
case
when ISNUMERIC(strangevalue)=1 THEN CONVERT(int,strangevalue)
ELSE strangevalue
END
FROM testing
best bet is to return two columns:
select
case
when ISNUMERIC(strangevalue)=1 THEN CONVERT(int,strangevalue)
ELSE NULL
END AS StrangvalueINT
,case
when ISNUMERIC(strangevalue)=1 THEN NULL
ELSE strangevalue
END AS StrangvalueString
FROM testing
or your application can test for numeric and do your special processing.
You can't have a column that is sometimes an integer and sometimes a string. Return the string and check it using int.TryParse() in the client code.
ISNUMERIC. However, this accepts +, - and decimals so more work is needed.
However, you can't have the columns as both datatypes in one go: you'll need 2 columns.
I'd suggest that you deal with this in your client or use an ISNUMERIC replacement
IsNumeric will get you part of the way there. You can then add some further code to check whether it is an integer
for example:
select top 10
case
when isnumeric(mycolumn) = 1 then
case
when convert(int, mycolumn) = mycolumn then
'integer'
else
'number but not an integer'
end
else
'not a number'
end
from mytable
To clarify some other answers, your SQL statement can't return different data types in one column (it looks like the other answers are saying you can't store different data types in one column - yours are all strign represenations).
Therefore, if you use ISNUMERIC or another function, the value will be cast as a string in the table that is returned anyway if there are other strigns being selected.
If you are selecting only one value then it could return a string or a number, however your front end code will need to be able to return the different data types.
Just to add to some of the other comments about not being able to return different data types in the same column... Database columns should know what datatype they are holding. If they don't then that should be a BIG red flag that you have a design problem somewhere, which almost guarantees future headaches (like this one).