What's wrong with my CASE? - sql

CASE WHEN table1.text IS NULL THEN table2.numbers
ELSE table1.text
END AS newcolumn
When running this code I keep getting this error:
ERROR: CASE types character varying and integer cannot be matched
You would think that this would not cause problems since I'm creating a new column within my query. I'd also like to point out that I'm using an old version of PostgreSQL if that helps.

CASE WHEN table1.text IS NULL THEN table2.numbers::text ELSE table1.text END AS newcolumn

Problem is you are trying to add table1.text and table2.numbers into a single column. These two columns are two diff data types. try following
CASE WHEN table1.text IS NULL THEN CAST(table2.numbers AS VARCHAR(50)) ELSE table1.text END AS newcolumn

The data type represented by table2.numbers and table1.text has to be the same, so it looks like in this case you'll need to CAST the value of table2.numbers

Try ISNULL
CASE WHEN ISNULL(table1.text) = 1 THEN table2.numbers ELSE table1.text END AS newcolumn

I think the error is pretty clear - the types of the two columns that may be used by the CASE statement aren't compatible.
Why would you think that trying to use values from two columns of different types would not cause problems? You may be creating a new column in the result set, but it still has to have a type and that has to match all the potential values.
It may be possible in a lot of cases for it to infer the type, but that's risky and may not necessarily be the choice that you want it to make, so it's better for it to force you to make the decision. You'll need to modify the type of one or the other columns in the CASE statement.

Related

Need to fetch Boolean type column as varchar from source table and store as varchar in target table in Amazon redshift

I have been working with redshift for a month. I need your help regarding this;
I need to create a target table using source table (create table target as select * from source), there is a column in source table type of boolean, I need to store that column as varchar in target table. Tried lots of methods like cast, convert..etc nothing worked for me. After done with lots of search, I got to know that boolean cannot be converted to another data type in redshift.
It shows me below error;
Amazon Invalid operation: column "indicator" is of
type boolean but expression is of type character varying; [SQL
State=42804, DB Errorcode=500310] 1 statement failed.
I shall be grateful for your help.
The following approach might work for your case.
When loading the data from source table, instead of selecting all the columns using SELECT *, you explicitly call out the individual columns and for the boolean column use a case expression and evaluate the actual data and return the result as string 'true' or 'false'.
create table target as select colA, colB, case boolColC when true then 'true' else 'false' end from source
If you can't convert directly from Boolean to varchar, you could use
CASE
WHEN boolCol= TRUE THEN 'True'
WHEN boolCol= FALSE THEN 'False'
ELSE 'Unknown'
END AS boolCol
to sidestep the need for conversion.
I am able to resolve the issue using nested case statement at the time of table creation - I am posting the solution here so that It can be helpful for others as well.
case
when name in ('a', 'b') then
case offline_crt when true then 'true' else 'false' end
else 'N/A'
end as indicator
The same issue I was also facing ,please check below how I fixed it.
In my original code one column having Boolean data type and when I was doing union of two table it was failing due to below error.
[Amazon](500310) Invalid operation: UNION types character varying and boolean cannot be matched;
I have attached the screenshot for your reference:
Now I have just used the case statement inside the select for the Boolean data type column and it's working fine.

SQL CASE with Alias

I am trying to change a column name based on the results of a case statement, is this possible and how would I do it...here is what I have so far but I am not good enough at SQL yet.
I want the change the column name of VALUE to become NUMVALUE if the data is numeric and ALNVALUE if the data isn't numeric. Essentially making a three column datatable a four column datatable. Is this possible?
CASE WHEN ISNUMERIC([Value])=1 THEN SELECT [VALUE] AS [NUMVALUE] ELSE SELECT [VALUE] AS [ALNVALUE] END
No, it isn't possible.
Think about the issues you'd run into when you try and use the result set. Anytime you tried to access the data, you would get an exception stating that the column couldn't be found or similar.
Dim data = Results["ColumnName"] would become unreliable.
You will need to make a separate column for each of them or put them all under the same name.
You need two CASEs = two columns:
SELECT
CASE WHEN ISNUMERIC([Value])= 1 THEN [VALUE] END AS [NUMVALUE],
CASE WHEN ISNUMERIC([Value])<>1 THEN [VALUE] END AS [ALNVALUE],
...
FROM myTable

SQL computed column evaluating numbers should return string

A similar question is here: Computed column should result to string
However in my case, I cannot cast the numeric values to strings. I need to evaluate the numbers and based on them return a text description. Is that possible?
ALTER TABLE dbo.test ADD classTest AS CASE
WHEN speed > 10 THEN 'fast'
ELSE 'error' END
Otherwise I suppose I can return numbers that correspond to text values in a look-up table and create a view...
Unfortunately I edited out my syntax error yesterday, I think I was missing the 'END' and an apostrophe somewhere. The fix didn't seem to work yesterday but I just tried it again and things are moving smoothly.
You were close. Just a couple of syntax errors. Single quotes and END
ALTER TABLE dbo.test ADD classTest AS CASE
WHEN speed > 10 THEN 'fast'
ELSE 'error' END
Select * from test
speed classTest
11 fast
5 error

PL/SQL Oracle condition equals

I think I'm encountering a fairly simple problem in PL/SQL on an Oracle Database(10g) and I'm hoping one of you guys can help me out.
I'm trying to explain this as clear as possible, but it's hard for me.
When I try to compare varchar2 values of 2 different tables to check if I need to create a new record or I can re-use the ID of the existing one, the DB (or I) compares these values in a wrong way. All is fine when both the field contain a value, this results in 'a' = 'a' which it understands. But when both fields are NULL (or '' which Oracle will turn into NULL) it can not compare the fields.
I found a 'solution' to this problem but I'm certain there is a better way.
rowTable1 ROWTABLE1%ROWTYPE;
iReUsableID INT;
SELECT * INTO rowTable1
FROM TABLE1
WHERE TABLE1ID = 'someID';
SELECT TABLE2ID INTO iReUsableID
FROM TABLE2
WHERE NVL(SOMEFIELDNAME,' ') = NVL(rowTable1.SOMEFIELDNAME,' ');
So NVL changes the null value to ' ' after which it will compare in the right way.
Thanks in advance,
Dennis
You can use LNNVL function (http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions078.htm) and reverse the condition:
SELECT TABLE2ID INTO iReUsableID
FROM TABLE2
WHERE LNNVL(SOMEFIELDNAME != rowTable1.SOMEFIELDNAME);
Your method is fine, unless one of the values could be a space. The "standard" way of doing the comparison is to explicitly compare to NULL:
WHERE col1 = col2 or col1 is null and col2 is null
In Oracle, comparisons on strings are encumbered by the fact that Oracle treats the empty string as NULL. This is a peculiarity of Oracle and not a problem in other databases.
In Oracle (or any RDBMS I believe), one NULL is not equal to another NULL. Therefore, you need to use the workaround that you have stated if you want to force 2 NULL values to be considered the same. Additionally, you might want to default NULL values to '' (empty) rather than ' ' (space).
From Wikipedia (originally the ISO spec, but I couldn't access it):
Since Null is not a member of any data domain, it is not considered a "value", but rather a marker (or placeholder) indicating the absence of value. Because of this, comparisons with Null can never result in either True or False, but always in a third logical result, Unknown.
As mentioned by Jan Spurny, you can use LNNVL for comparison. However, it would be wrong to say that a comparison is actually being made when both values being compared are NULL.
This is indeed a simple and usable way to compare nulls.
You cannot compare NULLS directly since NULL is not equal NULL.
You must provide your own logic who you would like to compare, what you've done with NVL().
Take in mind, you are treating NULLS as space, so ' ' in one table would be equal to NULL in another table in your case.
There are some other ways (e.g. LNNVL ) but they are not some kind of a "better" way, I think.

How do I handle nulls in NOT IN and NOT LIKE statements in Oracle?

I have a long piece of PL/SQL which is working well except for one small part of the where clause.
I'm expecting that one row should be returned but, because the fields the where clause checks are null, the row is not being returned despite meeting the criteria.
I read a very good note here :
http://jonathanlewis.wordpress.com/2007/02/25/not-in/
It explains how Nulls affect NOT IN statements and I presume it's the same for NOT LIKE as well.
What I haven't been able to find is the comparable replacement I need. Do I need to somehow switch this into an IN and LIKE or provide something to return the row if NUll?
Here is a simplified version of my code.
SELECT * FROM Temp_Table T
WHERE -- Other where constraints
AND (T.Col_One NOT LIKE 'AString'
OR T.Col_Two NOT IN ('BString','CString'))
In my situation the row would have nulls in both Col_One and Col_Two.
Any help is greatly appreciated.
Thanks.
Try this:
AND (NVL(T.Col_One,'NuLl') NOT LIKE 'AString'
OR NVL(T.Col_Two,'NuLl') NOT IN ('BString','CString'))
Something like this should work:
T.Col_One IS NULL OR T.Col_One NOT LIKE 'AString'
OR T.Col_Two IS NULL OR T.Col_Two NOT IN ('BString','CString')
Please note that...
T.Col_Two NOT IN ('BString','CString')
...is equivalent to...
T.Col_Two <> 'BString' AND T.Col_Two <> 'CString'
...which "collapses" to NULL in case T.Col_Two is NULL.
By convention NULL is not like or equal to anything - the only valid test would be IS NULL which will return true.
Check the NVL function in Oracle documentation in :
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions105.htm