Looking for an alternative to messy SQL ISNULL/NULLIF - sql

I have a SQL query running on SQL Server 2012 that needs to compare a bit value and return a string if that value is 1 and an empty string if it is zero.
Originally I had it as a CASE statement like this:
CASE WHEN myBit = 0 THEN
-- do other comparisons etc to build up the return string.
+'myString'
ELSE
-- do other comparisons etc to build up the return string.
'' END
The problem is that all of the code in 'do other' section is the same. All I want to do is append a string to the returned value if the bit is zero and nothing if it is 1.
So I refactored it to only have the common code once and then append to the string at the end like this:
-- do other comparisons etc to build up the return string. +
ISNULL(NULLIF(Cast(ISNULL(CAST(NULLIF(myBit, 0) AS NVARCHAR), 'myString') AS varchar),'0'),'')
However the above seems very messy not least because of the CAST statements required.
I'm looking for a clean and neat way of doing this but have run out of ideas - anyone have a better way of achieving this? Thanks.

Just add your CASE statement inline. Don't forget to return an empty string when mybit=1, or the whole thing will return NULL.
Select
-- do other comparisons etc to build up the return string.
+ Case When #mybit=0 Then mystring else '' End

You can also use IIF and CONCAT as you are on SQL Server 2012.
SELECT CONCAT('Start',
IIF(#mybit=0,'myString',''),
'End')
IIF is a bit more concise than CASE. CONCAT might be beneficial in that it casts non string types to strings automatically and concatenating NULL is treated the same as concatenating an empty string.

Also you can use a simple case here as;
Select 'Your other string ' +
Case mybit When 0 then 'mystring' else '' End As Results
--Results will be like
mybit Results
0 'Your other string mystring'
1 'Your other string '
OR if you want nothing (null) to return if mybit <> 0 then use a simple case without else part as;
Select 'Your other string ' + Case mybit When 0 then 'mystring' End As Results
--Results will be like
mybit Results
0 'Your other string mystring'
1 null
SQL-SERVER-DEMO for both cases

Can you put the common code into a subquery? It would resemble this:
select case when myBit = 0 then value else value + 'what you append' end returnvalue
from
(subquery with common code) abc
Or maybe a function
select case when myBit = 0 then yourfunction()
else yourfunction + 'what you append' end returnvalue

Related

Removing specified character from string in SQL

Say I have a string looking like this ",LI,PA,LK";
I want to remove the first char, so it looks like "LI,PA,LK";
In Java my code to handle this, will look like this:
public String returnSubs(String val) {
int index = val.indexOf(",");
String res = val.substring(index+1, val.length());
return res;
}
I want to achieve the exact same thing in SQL, having this query
select patientID, case when liver is not null then 'LI' else '' end
|| case when kidney_r is not null then ',KR' else '' end
|| case when kidney_l is not null then ',KL' else ''end
|| case when heart is not null then ',HE' else '' end
|| case when liver_domino is not null then ',LI-Dom' else '' end
|| case when lung_r is not null then ',LungR' else '' end
|| case when pancreas is not null then ',PA' else '' end
|| case when liver_split is not null then ',Lsplit' else '' end
|| case when lung_l is not null then ',LungL' else '' end
|| case when intestine is not null then ',Intestine' else '' end
into organType
from offers
where patientID > 1
;
Also, the string I get from the query above, could look like LI, PA, KL, (notice the comma is at the end, and not the begining)
I see that I can use the SUBSTRING and/or INSTR of SQL. But I'm not really sure how. I am creating a procedure where this will be handled
Thanks for any help
Oracle has a function trim() that does exactly what you want:
trim(leading ',' from col)
You can use this in either an update or select.
Note: You appear to be storing multiple values in a comma-delimited list. That is a very bad way to model data. You do not want to overload what strings are by storing multiple values. Oracle has many better alternatives -- association tables, nested tables, JSON, and XML come to mind.
You could also use LTRIM here:
SELECT
LTRIM(organTypes, ',') AS col_out
FROM offers;
Some databases, such as MySQL, offer functions like CONCAT_WS which concatenate with a separator while ensuring that no dangling separators are added to the resulting output. Oracle does not have this, but LTRIM should be sufficient here.
even this will work:
substr(',LI,PA,LK',2)
In SQL SERVER:
SUBSTRING(VAL,2,LEN(VAL))
VAL--> COLUMN NAME
2--> IT SKIPS 1ST VALUE
LEN-->LENGTH OF THE COLUMN

SQL Server CASE statement with multiple THEN clauses

I have seen several similar questions but none cover what I need. I need to put another THEN statement after the first one. My column contains int's. When it returns NULL I need it to display a blank space, but when I try the below code, I just get '0'.
CASE
WHEN Column1 IS NULL
THEN ''
ELSE Column1
END
If I try to put a sting after THEN then it tells me that it cannot convert it from int. I need to convert it to varchar and then change its output to a blank space afterwards, such as:
e.g.
CASE
WHEN Column1 IS NULL
THEN CONVERT(varchar(10), Column1)
THEN ''
ELSE Column1
END
Is there a way of doing this?
Thanks
Rob
A case expression returns a single value -- with a given type. If you want a string result, then you need to be sure that all paths in the case return strings:
CASE WHEN Column1 IS NULL
THEN ''
ELSE CAST(Column1 AS VARCHAR(255))
END
This is more simply written using COALESCE():
COALESCE(CAST(Column1 as VARCHAR(255)), '')
You cannot display an integer as a "blank" (other than using a NULL value).

SQL COALESCE and IS NULL are not returning a space when when the query returns NULL

I am trying to optimize a humongous SQL query that was written by a self taught developer that used a ton of functions instead of JOINS. Anyway, I am having trouble displaying a space or a empty string('') when there is no value in the field selected. I've included only the SELECT in question. I am having the weirdest problem or just overlooking the correct answer in troubleshooting. Whenever I use COALESCE, when the field is supposed to be a blank string, it displays a zero. And when I use IS NULL, I get back NULL. All info online seems to point toward using COALESCE(value, '') as depicted in the code. But I am getting a 0 instead of ''. Does anyone see what I'm doing wrong? I'm using SSMS.
SELECT
pss8.dbo.xml_StripIllegalChars(dbo.rpt_get_series_volume(b.bookkey)) AS p_seriesvol --SELECT to be replaced that works but is slow due to function use I am told
,COALESCE(bd.seriesvolume, '') AS p_seriesvol --my SELECT that won't work!
FROM
bookdetail bd
WHERE
--bd.bookkey='303177'
bd.bookkey='6002'
The bookkeys at the bottom are for testing as I know the top one returns a 1 and the bottom one returns a '' previously when it worked. The SELECT above my commented SELECT is the code that works but is slow... According to what I read online, I am saying 'if there isn't a series volume number, then it equals an empty string.' Does COALESCE not work like this? Can it only return a 0 if the field has no value, or in this case, has no volume number? All help much appreciated. I'm very curious to hear a solution!
Here's more intel. This is how the this SELECT works:
pss8.dbo.xml_StripIllegalChars(dbo.rpt_get_series_volume(b.bookkey)) AS p_seriesvol
The
.rpt_get_series_vol
function manages to create an empty string with this code... Does this reveal anything?
DECLARE #RETURN
VARCHAR(5)
DECLARE #v_desc
VARCHAR(5)
DECLARE #i_volumenumber INT
SELECT #i_volumenumber = volumenumber
FROM bookdetail
WHERE bookkey = #i_bookkey and volumenumber <> 0
IF #i_volumenumber > 0
BEGIN
SELECT #RETURN = CAST(#i_volumenumber as varchar(5))
END
ELSE
BEGIN
SELECT #RETURN = ''
END
RETURN #RETURN
END
As you are looking for a '0' not a NULL COALESCE()is not useful, instead use a simple CASE:
select
...,
case bd.seriesvolume when '0' then '' else bd.seriesvolume end as p_seriesvol
from
...
Or if you want '' for 0 or NULL
case when bd.seriesvolume is null or bd.seriesvolume = '0' then '' else bd.seriesvolume end as p_seriesvo
COALESCE() function returns the 1st non null value
SELECT COALESCE(NULL, NULL, 'third_value', 'fourth_value'); returns the third value because the third value is the first value that is not null.
So in your case COALESCE(bd.seriesvolume, '') AS p_seriesvol if seriesvolume colum value is null then it will return blank string

How do identify the first character of a string as numeric or character in SQL

I need to identify the first character in my data as numeric or character in SQL Server. I am relatively new to this and I don't know where to begin on this one. But here is what I have done to this point. I had data that looked like this:
TypeDep
Transfer From 4Z2
Transfer From BZZ
Transfer From 123
Transfer From abc
I used the right function to remove the 'transfer from' and isolate the data I need to check.
UPDATE #decode
SET firstPartType = Right(z.TypeDep,17)
FROM #decode z
where z.TypeDep like 'TRANSFER FROM%'
firstPartType
4Z2
BZZ
123
abc
Now I need to add a column identifying the first character in the string. Producing the results below.
firstPartType SecondPartType
4Z2 Numeric
BZZ Alpha
123 Numeric
abc Alpha
Using LEFT and ISNUMERIC(), however be aware that ISNUMERIC thinks some additional characters such as . are numeric
UPDATE #decode
SET SecondPartType =
CASE WHEN ISNUMERIC(LEFT(firstPartType, 1)) = 1 THEN'Numeric'
ELSE 'Alpha'
END
FROM #decode;
A more robust approach is to use the limited regex functionality of sql server. ISNUMERIC will return false positives for single characters like .,$ to name a few.
SELECT
CASE WHEN left(firstPartType, 1) like '[0-9]' THEN 'Numeric'
ELSE 'Alpha'
END AS SecondPartType
I think this should work:
SELECT
CASE WHEN ISNUMERIC(SUBSTRING(firstPartType, 1, 1)) = 1
THEN 'Numeric'
ELSE 'Alpha'
END AS 'SecondPartType'
FROM TABLE
you can use this command
ISNUMERIC(LEFT(firstPartType, 1))
this return 1 if the first character is a Numbert
0 if isn't.
i think is all you need
You could try:
UPDATE #decode
SET SecondPartType =
CASE
WHEN LEFT(firstPartType, 1) IN ('0','1','2','3','4','5','6','7','8','9')
THEN'Numeric'
ELSE 'Alpha'
END
FROM #decode;
select ISNUMERIC(left('4ello world',1)) will be a "1" if the first character is a number.

REPLACE empty string

I discover some behavior I didn't know before. Why this line of code does not work?
SELECT REPLACE('','','0') ==> returns ''
I can't even have '' in where condition. It just doesn't work. I have this from imported Excel where in some cells are no values but I'm not able to remove them unless I used LEN('') = 0 function.
There is nothing to replace in an empty string. REPLACE replaces a sequence of characters in a string with another set of characters.
You could use NULLIF to treat it as NULL + COALESCE (or ISNULL):
declare #value varchar(10);
set #value = '';
SELECT COALESCE(NULLIF(#value,''), '0')
This returns '0'.
You can use CASE for this.
(CASE WHEN *YOURTHING* = '' THEN '0' ELSE *YOURTHING* END)
AS *YOURTHING*
It does work. There are two proper behaviors here - first one is to return back empty string (what it does already), second one is to return infinite string full of zeroes.
Solved! > Check multiple scenarios like '', remove spaces, Null, string/numeric result
SELECT CASE WHEN LTRIM(RTRIM(ISNULL(mob, 0))) = '' THEN '0' ELSE LTRIM(RTRIM(ISNULL(mob, 0))) END MobileNo
FROM table1 WHERE emp_no = '01111'