Return Character from Numeric Field using Cast & Coalesce - sql

Using SQL Server 2008 R2
Relatively basic SQL user, apologies if this is a simple question but need a little help to tidy up the output of a fairly complex script I have been given.
I have a number of columns being returned for which where there is a NULL, I want to replace all NULL's with a standard set of characters, currently "---". Using ISNULL works for most columns. However, for some columns we are looking at 2 tables to find a value so have after doing some research on here, I have modified a line I am having trouble with as follows:
Previous
isnull (ff.ff_sales,aa.ff_sales) as 'Total Revenue'
Latest
cast(coalesce(ff.ff_sales,aa.ff_sales,'') as FLOAT) as 'Total Revenue'
The initial line returned 'NULL' if both ff.ff_sales & aa.ff_sales were empty, now with the latest line using cast & coalesce I get '0'. However, I am trying to achieve a situation where I get '---' as per all other fields where a NULL exists. I don't want it to return '0' for a Sales field as this is misleading. I have tried using VARCHAR instead of FLOAT but am unsure if this is the right thing to do at this stage?
1st column is using ISNULL, 2nd column current output with cast & coalesce, 3rd column is what I want to get to:
Total Revenue Total Revenue Total Revenue
67755 67755 67755
6.123 6.123 6.123
494.75 494.75 494.75
0 0 0
1139909 1139909 1139909
12346.45 12346.45 12346.45
129.866 129.866 129.866
NULL 0 ---
NULL 0 ---
554 554 554
Thanks for your help!

You can use case to decide what should be output in this scenario, like so:
select
case
when isnull (ff.ff_sales,aa.ff_sales) is null then '---'
else cast(isnull (ff.ff_sales,aa.ff_sales) as varchar)
end as 'Total Revenue'
This will force the output to be returned as varchar though, because you cannot cast '---' as a numeric type.
Alternatively, you could just let the value be NULL in DB, and in your presentation layer, replace a DBNull or equivalent value with '---'. This will let you keep total revenue as a numeric field at the DB level.

Related

How to update status to wrong numeric if at least on character exist?

I work on SQL server 2012 I have issue I can't update status to Numbers only when whole field have digits only from 0 to 9 .
but if it have only one character or precision then it will be not valid .
1222 valid
223g not valid
create table #acceptnumbersOnly
(
KeyValue nvarchar(50),
Status nvarchar(50)
)
insert into #acceptnumbersOnly(KeyValue)
values
('233'),
('g25k'),
('25k'),
('gkg'),
('145'),
('45.5')
Expected result will be :
KeyValue Status
233 Numbers only
g25k Not Valid Numbers Only
25k Not Valid Numbers Only
gkg Not Valid Numbers Only
145 Numbers only
45.5 Not Valid Numbers Only
Something like this
update #acceptnumbersOnly
set
[Status]=iif(KeyValue LIKE '%[^0-9]%', 'Not Valid Numbers Only', 'Numbers only');
Results
KeyValue Status
233 Numbers only
g25k Not Valid Numbers Only
25k Not Valid Numbers Only
gkg Not Valid Numbers Only
145 Numbers only
45.5 Not Valid Numbers Only
I grew up with the Case...When logic. This works for me.
SELECT KeyValue,
CASE
WHEN KeyValue LIKE '%[^0-9]%' THEN 'Not Valid Numbers Only'
ELSE 'Numbers only'
END AS Status
FROM #acceptnumbersOnly
I always thought IIF was for MS Access. I just found out about the IIF function right now. Apparently IIF was introduced in SQL Server 2012+. I would think the Case...When is a better solution, as it is portable across all versions of SQL Server. MAybe it's a moot point, because there probably are not too many people out there using pre-2012 SQL Server.

Error converting data type nvarchar to numeric - SQL Server

I am trying to take an average of a column in my database. The column is AMOUNT and it is stored as NVARCHAR(300),null.
When I try to convert it to a numeric value I get the following error:
Msg 8114, Level 16, State 5, Line 1
Error converting datatype NVARCHAR to NUMBER
Here is what I have right now.
SELECT AVG(CAST(Reimbursement AS DECIMAL(18,2)) AS Amount
FROM Database
WHERE ISNUMERIC(Reimbursement) = 1
AND Reimbursement IS NOT NULL
You would think that your code would work. However, SQL Server does not guarantee that the WHERE clause filters the database before the conversion for the SELECT takes place. In my opinion this is a bug. In Microsoft's opinion, this is an optimization feature.
Hence, your WHERE is not guaranteed to work. Even using a CTE doesn't fix the problem.
The best solution is TRY_CONVERT() available in SQL Server 2012+:
SELECT AVG(TRY_CONVERT(DECIMAL(18,2), Reimbursement)) AS Amount
FROM Database
WHERE ISNUMERIC(Reimbursement) = 1 AND Reimbursement IS NOT NULL;
In earlier versions, you can use CASE. The CASE does guarantee the sequential ordering of the clauses, so:
SELECT AVG(CASE WHEN ISNUMERIC(Reimbursement) = 1 AND Reimbursement IS NOT NULL
THEN CONVERT(DECIMAL(18,2), Reimbursement))
END)
FROM Database;
Because AVG() ignores NULL values, the WHERE is not necessary, but you can include it if you like.
Finally, you could simplify your code by using a computed column:
alter database add Reimbursement_Value as
(CASE WHEN ISNUMERIC(Reimbursement) = 1 AND Reimbursement IS NOT NULL
THEN CONVERT(DECIMAL(18,2), Reimbursement))
END);
Then you could write the code as:
select avg(Reimbursement_Value)
from database
where Reimbursement_Value is not null;
Quote from MSDN...
ISNUMERIC returns 1 for some characters that are not numbers, such as plus (+), minus (-), and valid currency symbols such as the dollar sign ($). For a complete list of currency symbols, see money and smallmoney
select isnumeric('+')---1
select isnumeric('$')---1
so try to add to avoid non numeric numbers messing with your ouput..
WHERE Reimbursement NOT LIKE '%[^0-9]%'
If you are on SQLServer 2012,you could try using TRY_Convert which outputs null for conversion failures..
SELECT AVG(try_convert( DECIMAL(18,2),Reimbursement))
from
table
I am guessing that since it is Nvarchar you are going to find some values in there with a '$','.', or a (,). I would run a query likt this:
SELECT Amount
FROM database
WHERE Amount LIKE '%$%' OR
Amount LIKE '%.%' OR
Amount LIKE '%,%'
See what you get and my guess you will get some rows returned and then update those rows and try it again.
Currently your query would pull all numbers that are not all numeric which is a reason why it is failing too. Instead try running this:
SELECT AVG(CAST(Reimbursement AS DECIMAL(18,2)) AS Amount
FROM Database
--Changed ISNUMERIC() = to 0 for true so it will only pull numeric numbers.
WHERE ISNUMERIC(Reimbursement) = 0 and Reimbursement IS NOT NULL

Updating with case in SQL Server 2008 R2

I want to update a column according to another column value.
for example, In Value column i have numbers between 0 to 1.
I want to check values and if:
Values < 0.45 set ValueStatus=Bad
Values >=0.45 and values<0.55 set ValueStatus =SoSo
Values >= 0.55 set ValueStatus=Good
I wrote the query like this:
update table
set ValueStatus=(case
when Values<'0.45' then 'Bad'
when (Values>='0.45' and Values<'0.55') then 'SoSo'
when Values>='0.55' then 'Good'
else Values
end)
But i get this error :
Error converting data type varchar to float.
Type of Values is Float and ValueStatus is Nvarchar(50)
Thanks
try this (you were adding ' to the numbers and SQL takes them as varchar) :
update table
set ValueStatus=(case when Values<0.45 then 'Bad'
when Values>=0.45 and Values<0.55 then 'SoSo' when Values>=0.55
then 'Good' else Values end )
I believe your problem is based on how the case statement determines the return type. You can read about it here and here.
The numeric types have a higher precedence than the string types. With the else values, you have four clauses in the `case. Three return strings; one returns a number. The number trumps the types so it tries to turn everything into a number.
You can mimic this problem with:
select (case when 1=1 then 'abc' else 12.3 end)
Happily, you can fix this by removing the else clause which is not needed in this case.

DB2 SQL - How can I display nothing instead of a hyphen when the result of my case statement is NULL?

All,
I'm writing a query that includes a CASE statement which compares two datetime fields. If Date B is > Date A, then I'd like the query to display Date B. However, if Date B is not > Date A, then the user who will be getting the report created by the query wants the column to be blank (in other words, not contain the word 'NULL', not contain a hyphen, not contain a low values date). I've been researching this today but have not come up with a viable solution so thought I'd ask here. This is what I have currently:
CASE
WHEN B.DTE_LNP_LAST > A.DTE_PROC_ACT
THEN B.DTE_LNP_LAST
ELSE ?
END AS "DATE OF DISCONNECT"
If I put NULL where the ? is, then I get a hyphen (-) in my query result. If I omit the Else statement, I also get a hyphen in the query result. ' ' doesn't work at all. Does anyone have any thoughts?
Typically the way nulls are displayed is controlled by the client software used to display query results. If you insist on doing that in SQL, you will need to convert the date to a character string:
CASE
WHEN B.DTE_LNP_LAST > A.DTE_PROC_ACT
THEN VARCHAR_FORMAT(B.DTE_LNP_LAST)
ELSE ''
END AS "DATE OF DISCONNECT"
Replace VARCHAR_FORMAT() with the formatting function available in your DB2 version on your platform, if necessary.
You can use the coalesce function
Coalesce (column, 'text')
If the first value is null, it will be replaced by the second one.

SQL Use Text and Decimal in the same column

I have a requirement to fill in all NULL fields with DEL. I don't want to modify the database tables, I would just like to do it in on column. Below is what I'm trying to do right now. Basically if the value is not null then I want 132.00. If it is null then I want to see DEL. I'm working on SQL 2008 R2. Thank you for your help its greatly appreciated.
Current thought
CASE WHEN [Sales] IS NOT NULL
THEN CAST([Sales] AS decimal(10,0))
ELSE 'DEL'
END AS Sales
Error
Error converting data type varchar to numeric.
Warning: Null value is eliminated by an aggregate or other SET operation.
CASE WHEN [Sales] IS NOT NULL
THEN CAST(CAST([Sales] AS decimal(10,0)) AS NVARCHAR(1000))
ELSE CAST(DEL AS NVARCHAR(1000))
END AS Sales
In a case statement in every ease the returned data type must be the same.
EDIT
To return string DEL if sales is null you can do
CASE WHEN [Sales] IS NOT NULL
THEN CAST(CAST([Sales] AS decimal(10,0)) AS NVARCHAR(1000))
ELSE 'DEL'
END AS Sales
You can't store the 'DEL' text in a column defined to hold decimals. It's just not possible. What is more, you shouldn't store decimal values in a columned defined to hold strings. In other words, this requirement is backwards and wrong.
What you can do is continue to store NULL and decimal data as you have before, and just return string data for display:
CASE WHEN [sales] IS NULL THEN 'DEL' ELSE Convert(varchar(13), [sales]) END
However, this is also less than the ideal, as it forces your database to do the conversion work, and means your client code starts out working with strings rather than numbers. The best option here is to have the database continue to work with the raw data as it is, and make the adjustment to change NULLs to 'DEL' in your client code.