If-Then Statement In A SQL Query Insists On Trying To Convert To Wrong Type, Then Fails - sql

I have a SQL query, linking table 1 to table 2 via an inner join, containing this part in the select part of the statement:
select
table1.field1,
table2.field1,
CASE (table2.field1)
WHEN -2 THEN ''
ELSE table2.field2
END as table2Field2,
table3.field4
from...
I want to be able to return table2Field2 when it has a relevant value, ie: when the object represented in table2 is not null, so that table2.field1 does not have a value of -2. In this case, the value of table2Field2 should be blank instead of a meaningless value.
However, this returns 0 instead of the blank text. If I change this line:
WHEN -2 THEN ''
to this:
WHEN -2 THEN 'someText'
then it complains at me that it's trying to convert an int to a string, which I'm not. table2field1 is an int, but table2Field2 is a string, which is what we're actually returning here.
How do I state (even more specifically) in this query that I'm returning the string field as a string, and not something else as a string that isn't (a) a string, and (b) the thing I specified I'm returning please?
All suggestions welcome, many thanks in advance for any help :)

In a CASE expression, all of the possible return values must be of the same data type. As written, the expression is trying to return one string and one integer.
If you want an empty string for your first output, you can CAST or CONVERT your second output to a character type value:
select
table1.field1,
table2.field1,
CASE (table2.field1)
WHEN -2 THEN ''
ELSE CAST(table2.field2 AS varchar(12)) --< 12 will cover any value of integer.
END as table2Field2,
table3.field4
from...

Is it possible you have your as table2field2 in the wrong location?
maybe try:
select
table1.field1,
table2.field1,
CASE (table2.field1)
WHEN -2 THEN ''
ELSE table2.field2
END as table2Field2,
table3.field4
from...

Because you do not want to answer me what is the database you use then I have to do it like this hehehe:
SQL Server: DEMO
select
t.col1,
CASE
WHEN convert(char,t.col1) = '-2' THEN 'aaa'
ELSE convert(char,(t.col2))
END test
from Tab1 t;
Oracle DEMO
select
t.col1,
CASE
WHEN to_char(t.col1) = '-2' THEN 'aaa'
ELSE to_char(t.col2)
END test
from tab1 t;

Related

Invalid argument for function integer IBM DB2

I need to filter out rows in table where numer_lini column has number in it and it is between 100 and 999, below code works just fine when i comment out line where i cast marsnr to integer. However when i try to use it i get error: Invalid character found in a character string argument of the function "INTEGER". when looking at the list seems like replace and translate filters only numbers just fine and select only contains legit numbers (list of unique values is not long so its easy to scan by eye). So why does it fail to cast something? I also tried using integer(marsnr), but it produces the same error. I need casting because i need numeric range, otherwise i get results like 7,80 and so on. As I mentioned Im using IBM DB2 database.
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where numer_lini in (
select marsnr
from (
select
distinct numer_lini marsnr
from alaska.trasa
where case
when replace(translate(numer_lini, '0','123456789','0'),'0','') = ''
then numer_lini
else 'no'
end <> 'no'
)
where cast(marsnr as integer) between 100 and 999
)
fetch first 300 rows only
If you look at the optimized SQL from the Db2 explain, you will see that Db2 has collapsed your code into a single select.
SELECT DISTINCT Q2.NUMER_LINI AS "NUMER_LINI",
Q2.WAR_TRASY AS "WAR_TRASY",
Q2.ID_PRZ1 AS "ID_PRZ1",
Q2.ID_PRZ2 AS "ID_PRZ2",
Q1.NUMER_LINI
FROM ALASKA.TRASA AS Q1,
ALASKA.TRASA AS Q2
WHERE (Q2.NUMER_LINI = Q1.NUMER_LINI)
AND (100 <= INTEGER(Q1.NUMER_LINI))
AND (INTEGER(Q1.NUMER_LINI) <= 999)
AND (CASE WHEN (REPLACE(TRANSLATE(Q1.NUMER_LINI,
'0',
'123456789',
'0'),
'0',
'') = '') THEN Q1.NUMER_LINI
ELSE 'no' END <> 'no')
Use a CASE to force Db2 to do the "is integer" check first. Also, you don't check for the empty string.
E.g. with this table and data
‪create‬‎ ‪TABLE‬‎ ‪alaska‬‎.‪trasa‬‎ ‪‬‎(‪numer_lini‬‎ ‪VARCHAR‬‎(‪10‬‎)‪‬‎,‪‬‎ ‪war_trasy‬‎ ‪INT‬‎ ‪‬‎,‪‬‎ ‪id_prz1‬‎ ‪INT‬‎,‪‬‎ ‪id_prz2‬‎ ‪INT‬‎)‪;
insert into alaska.trasa values ('',1,1,1),('99',1,1,1),('500',1,1,1),('3000',1,1,1),('00300',1,1,1),('AXS',1,1,1);
This SQL works
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where case when translate(numer_lini, '','0123456789') = ''
and numer_lini <> ''
then integer(numer_lini) else 0 end
between 100 and 999
Although that does fail if there is an embedded space in the input. E.g. '30 0'. To cater for that, a regular expressing is probably preferred. E.g.
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where case when regexp_like(numer_lini, '^\s*[+-]?\s*((\d+\.?\d*)|(\d*\.?\d+))\s*$'))
then integer(numer_lini) else 0 end
between 100 and 999

SQL: If field is empty, return empty string, otherwise cast as number

I'm running SQL Server 2008 (otherwise I would use Try_Parse) and I need to cast a field as a number in cases where it is non-empty. If the field is empty, an empty string or NULL should be returned. I would prefer if the field was stored as a number in the database, but I have no control over that at this time.
Here is what I have tried:
SELECT CASE WHEN AccountNumber='' THEN '' ELSE CAST(AccountNumber AS bigint) END AS AccountNumber FROM Accounts
OR
SELECT CASE WHEN CAST(AccountNumber AS bigint)=0 THEN '' ELSE CAST(AccountNumber AS bigint) END AS AccountNumber FROM Accounts
But both of these bring back 0 for empty account numbers. I feel that this should be possible but I am going crazy trying to figure it out! Thanks!
You can't select both numbers and empty strings into the same column, because they are incompatible types. That's why the empty strings get converted automatically to 0. NULL should work, however.
SELECT CASE WHEN AccountNumber='' OR AccountNumber IS NULL THEN NULL
ELSE CAST(AccountNumber AS bigint) END AS AccountNumber
FROM Accounts
You can use ISNUMERIC function:
SELECT CASE WHEN ISNUMERIC(AccountNumber) = 1 THEN CAST(AccountNumber AS BIGINT) ELSE NULL END
FROM Accounts

Replacing "(null)" with blank cell in SQL query result

I believe what I'm asking here is possible, but I haven't find a way yet :
Some cells in the result of my SQL SELECT-FROM-WHERE query are blank, and in DbVisualizer, (null) is written inside. I'd like to display a blank cell instead.
I've already tried with CASE-WHEN and the NVL operator, but it won't let me replace it by a blank '', I'm forced to use some ' ' or 'message'.
I know I could just delete these spaces or messages with Excel later, but I'd like to know if there is a way to do it directly with DbVisualizer, instead of this workaround.
EDIT: Here is what my request looks like :
SELECT *things*,
CASE WHEN
(SELECT COUNT(*) FROM table d2 WHERE *join-condition* AND *other condition*) = 1
THEN
(*sub-select query*)
ELSE
''
END
AS NAME,
*other things*
FROM table d1
WHERE *something*
Thanks a lot !
Did you try standard SQL function coalesce(), as below ?
SELECT COALESCE(columnName, '') AS ColumnName FROM tableName;
Syntax:
COALESCE (expr1, expr2)
is equivalent to:
CASE WHEN expr1 IS NOT NULL THEN expr1 ELSE expr2 END
Similarly,
COALESCE (expr1, expr2, ..., exprn), for n>=3
is equivalent to:
CASE WHEN expr1 IS NOT NULL THEN expr1
ELSE COALESCE (expr2, ..., exprn) END
Above examples are from Database SQL Language Reference
The problem in your query is the following ELSE part of the CASE expression:
ELSE
''
In Oracle, an empty string is considered as NULL value. So, all you need to do is use something else instead of ''.
For example, to use a space instead of NULL:
ELSE
' '
Update The issue is the DbVisualizer tool. OP is on version 8.0.12. Prior to version 9.2.8 it cannot show NULL as an empty string. However, as discussed in this forum, it has been fixed in DbVisualizer 9.2.8.
Standard SQL provides COALESCE(expr1, expr2, ...) as suggested by #Shishir.
COALESCE() takes a variable amount of arguments and returns the first expression that is NOT NULL
MySQL also provides IFNULL(expr1,expr2), which returns expr2 when expr1 IS NULL
Examples
SELECT
COALESCE(field1, ''),
COALESCE(field1, field2, field3)
IFNULL(field1, ''),
IFNULL(field1, field2)
FROM table

Error: invalid input syntax for integer: ""

I have this table tbl_buku:
id_buku judul_buku tahun_buku
1 Bioogi 2010
2 Fisika 2010
3 Informatika 2012
4 Kimia 2012
I use query like this, but I am getting an error:
select case when t1.tahun_buku=t2.tahun_buku then ''
else t1.tahun_buku end tahun_buku,t1.judul_buku
from tbl_buku t1 left join tbl_buku t2
on t1.id_buku-1=t2.id_buku;
I want to show table like this:
tahun_buku judul_buku
2010 Biologi
Fisika
2012 Informatika
Kimia
How to achieve this?
I think the problem in your query is that tahun_buku is of datatype int and you are trying to select an empty string ('').
You have to workarounds:
Change tahun_buku to be varchar (2010,2012..will be consider as strings I dont know if it is ok)
Set:
select case when t1.tahun_buku=t2.tahun_buku then null else t1.tahun_buku end tahun_buku,t1.judul_buku
from tbl_buku t1 left join tbl_buku t2
on t1.id_buku-1=t2.id_buku;
Use the window function lag() to get values from the previous row.
Use NULL for "empty" values in a numeric column - like #apomene already suggested.
The empty string '' can only be used in character types like text or varchar.
Use NULLIF() in this particular case to substitute the NULL value.
SELECT NULLIF(lag(tahun_buku) OVER (ORDER BY tahun_buku, judul_buku)
, tahun_buku) AS tahun_buku
, judul_buku
FROM tbl_buku
ORDER BY tahun_buku, judul_buku;

Specify order of (T)SQL execution

I have seen similar questions asked elsewhere on this site, but more in the context of optimization.
I am having an issue with the order of execution of the conditions in a WHERE clause. I have a field which stores codes, most of which are numeric but some of which contain non-numeric characters. I need to do some operations on the numeric codes which will cause errors if attempted on non-numeric strings. I am trying to do something like
WHERE isnumeric(code) = 1
AND CAST(code AS integer) % 2 = 1
Is there any way to make sure that the isnumeric() executes first? If it doesn't, I get an error...
Thanks in advance!
The only place order of evaluation is guaranteed is CASE
WHERE
CASE WHEN isnumeric(code) = 1
THEN CAST(code AS integer) % 2
END = 1
Also just because it passes the isnumeric test doesn't guarantee that it will successfully cast to an integer.
SELECT ISNUMERIC('$') /*Returns 1*/
SELECT CAST('$' AS INTEGER) /*Fails*/
Depending upon your needs you may find these alternatives preferable.
Why not simply do it using LIKE?:
Where Code Not Like '%[^0-9]%'
Btw, either using my solution or using IsNumeric, there are some edge cases which might lead one to using a UDF such as 1,234,567 where IsNumeric will return 1 but Cast will throw an exception.
Why not use a CASE statement to say something like:
WHERE
CASE WHEN isnumeric(code) = 1
THEN CAST(code AS int) % 2 = 1
ELSE /* What ever else if not numeric */ END
You could do it in a case statement in the select clause, then limit by the value in an outer select
select * from (
select
case when isNum = 1 then CAST(code AS integer) % 2 else 0 end as castVal
from (
select
Case when isnumeric(code) = 1 then 1 else 0 end as isNum
from table) t
) t2
where castval = 1