Converting to money format - sql

I have following query trying to apply money format.
select case when c.num is null
then 0.00
else '$' + Convert(varchar,CONVERT(money(c.total+c.customerS),1),2)
end verified
from table_Sales c
where c.id=#id
When I run this it gives error it couldn't convert varchar to numeric. When i change
varchar to integer or numeric it doesn't do anything.
Please let me know how to fix it.

Whilst I appreciate this is not a direct answer, I would strongly advocate NOT formatting numeric data to strings in the data layer.
It feels to me a lot more like the type of logic which would or could be application specific. What if you want to re-use the same query to work with GBP or Euros?
Additionally, what if your application needs to handle more than one currency?
I would suggest returning the data without the addition of the currency symbol in decimal form and applying the formatting within the application or on the client side if web based maybe.
Just my 2c(or 2p)

Both types in Case Clause must be same, so 0.00 must be '0.00'
Query:
select case when c.num is null
then '0.00'
else '$' + Convert(varchar,CONVERT(money(c.total+c.customerS),1),2)
end verified
from table_Sales c
where c.id=#id

Related

Converting a large decimal with percentage sign (%) to a smaller decimal

I have the following data that I need to convert to a simple decimal. Currently, it is in varchar format. The data is in a column called Commission%
Commission% (currently Varchar)
Commission% V2 (needs to be decimal)
87.00000%
.87
95.00000%
.95
I have tried the following:
CAST(CAST(CONVERT(FLOAT,REPLACE([Commission %], ''%'', '''')) / 100 AS DECIMAL(10,6)) as DECIMAL(10,6))
BUT I get the following error message Error converting data type varchar to numeric. I was able to use something similar the other day but there were fewer trailing zero's at the time.
This is almost certainly due to bad data which is what you should expect when you store numbers as strings. Here is how you identify them:
SELECT [KeyColumn], [Commission%]
FROM dbo.BadColumnNamesWow
WHERE [Commission%] IS NOT NULL
AND TRY_CONVERT(decimal(20,10), REPLACE([Commission%], '%', '')) IS NULL;
Since you now say there are other patterns, it might make sense to just do this to identify all of the bad data:
SELECT * FROM dbo.BadColumnNamesWow
WHERE [Commission%] IS NOT NULL
AND PATINDEX('%[^0-9.]%', [Commission%]) > 0;
Then clean it up. This should be a lesson in why you never store numeric values in string columns.

Error Converting data type Discount amount vs fixed amount

Good day
This is the code I am using and it gives an error "Error converting data type varchar to numeric"
select InvPrice.StockCode, InvPrice.SellingPrice,
SorContractPrice.StartDate, SorContractPrice.ExpiryDate, SorContractPrice.PriceMethod, SorContractPrice.FixedPrice, SorContractPrice.Discount1,InvPrice.SellingPrice
From InvPrice
Inner Join
SorContractPrice
on SorContractPrice.StockCode = InvPrice.StockCode
where SorContractPrice.PriceMethod IN
(case when SorContractPrice.PriceMethod = 'F' then SorContractPrice.FixedPrice
when SorContractPrice.PriceMethod = 'D' then InvPrice.SellingPrice - SorContractPrice.Discount1
else SorContractPrice.FixedPrice
end)
I need to deduct the discount from the fixed price alternatively it should stay as the fixed price.
Sorry I am very new to sql
Your assistance is highly appreciated.
You can use try_convert on one of the items that you are going to use to minus off. convert method works too. [If the first item doesn't work, you can try it on the alternate one. But if you already know which one holds the varchar value, then use it on that one.] You can basically convert both of them to the same value (float or numeric)
If you need a short guide on how to use those , here it is : http://sqlhints.com/2013/06/08/try_convert-sql-server-2012-built-in-conversion-function/
But remember that it will not convert it for you if it simply cant. If it can't it just means that the data you are using for varchar most likely isn't a number ,etc.
Also, what #KD commented, cast also helps too.
Hope this helps you out.

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

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.

How does one filter based on whether a field can be converted to a numeric?

I've got a report that has been in use quite a while - in fact, the company's invoice system rests in a large part upon this report (Disclaimer: I didn't write it). The filtering is based upon whether a field of type VarChar(50) falls between two numeric values passed in by the user.
The problem is that the field the data is being filtered on now not only has simple non-numeric values such as '/A', 'TEST' and a slew of other non-numeric data, but also has numeric values that seem to be defying any type of numeric conversion I can think of.
The following (simplified) test query demonstrates the failure:
Declare #StartSummary Int,
#EndSummary Int
Select #StartSummary = 166285,
#EndSummary = 166289
Select SummaryInvoice
From Invoice
Where IsNull(SummaryInvoice, '') <> ''
And IsNumeric(SummaryInvoice) = 1
And Convert(int, SummaryInvoice) Between #StartSummary And #EndSummary
I've also attempted conversions using bigint, real and float and all give me similar errors:
Msg 8115, Level 16, State 2, Line 7
Arithmetic overflow error converting
expression to data type int.
I've tried other larger numeric datatypes such as BigInt with the same error. I've also tried using sub-queries to sidestep the conversion issue by only extracting fields that have numeric data and then converting those in the wrapper query, but then I get other errors which are all variations on a theme indicating that the value stored in the SummaryInvoice field can't be converted to the relevant data type.
Short of extracting only those records with numeric SummaryInvoice fields to a temporary table and then querying against the temporary table, is there any one-step solution that would solve this problem?
Edit: Here's the field data that I suspect is causing the problem:
SummaryInvoice
11111111111111111111111111
IsNumeric states that this field is numeric - which it is. But attempting to convert it to BigInt causes an arithmetic overflow. Any ideas? It doesn't appear to be an isolated incident, there seems to have been a number of records populated with data that causes this issue.
It seems that you are gonna have problems with the ISNUMERIC function, since it returns 1 if can be cast to any number type (including ., ,, e0, etc). If you have numbers longer than 2^63-1, you can use DECIMAL or NUMERIC. I'm not sure if you can use PATINDEX to perform an regex look on SummaryInvoice, but if you can, then you should try this:
SELECT SummaryInvoice
FROM Invoice
WHERE ISNULL(SummaryInvoice, '') <> ''
AND CASE WHEN PATINDEX('%[^0-9]%',SummaryInvoice) > 0 THEN CONVERT(DECIMAL(30,0), SummaryInvoice) ELSE -1 END
BETWEEN #StartSummary And #EndSummary
You can't guarantee what order the WHERE clause filters will be applied.
One ugly option to decouple inner and outer.
SELECT
*
FROM
(
Select TOP 2000000000
SummaryInvoice
From Invoice
Where IsNull(SummaryInvoice, '') <> ''
And IsNumeric(SummaryInvoice) = 1
ORDER BY SummaryInvoice
) foo
WHERE
Convert(int, SummaryInvoice) Between #StartSummary And #EndSummary
Another using CASE
Select SummaryInvoice
From Invoice
Where IsNull(SummaryInvoice, '') <> ''
And
CASE WHEN IsNumeric(SummaryInvoice) = 1 THEN Convert(int, SummaryInvoice) ELSE -1 END
Between #StartSummary And #EndSummary
YMMV
Edit: after question update
use decimal(38,0) not int
Change ISNUMERIC(SummaryInvoice) to ISNUMERIC(SummaryInvoice + '0e0')
AND with IsNumeric(SummaryInvoice) = 1, will not short circuit in SQL Server.
But may be you can use
AND (CASE IsNumeric(SummaryInvoice) = 1 THEN Convert(int, SummaryInvoice) ELSE 0 END)
Between #StartSummary And #EndSummary
Your first issue is to fix your database structure so bad data cannot get into the field. You are putting a band-aid on a wound that needs stitches and wondering why it doesn't heal.
Database refactoring is not fun, but it needs to be done when there is a data integrity problem. I assume you aren't really invoicing someone for 11,111,111,111,111,111,111,111,111 or 'test'. So don't allow those values to ever get entered (if you can't change the structure to the correct data type, consider a trigger to prevent bad data from going in) and delete the ones you do have that are bad.