SQL Server - How to check if string is text or any representation of 0? - sql

I have a 'non-clean' column Col1 of type nvarchar(20) containing numbers (both integers and decimals) and various representations of the text 'No Data'
(e.g no-data, no data, NO DATA, etc) for cases where the value cannot be found.
Am looking for a query which will fetch me only records that contain ANY representation of 0 (like 0, 00, 0.00 etc) or the exact text 'NO-DATA'.
I am unable to find ways to use regular expression in SQL Server 2016.

This should be pretty simple:
select (case when try_convert(float, col) = 0 then 1 else 0 end) as IsZero
try_convert() returns NULL if the conversion doesn't work.
In general, comparison of floating point numbers to constants isn't recommended. In this case, I'm pretty sure all reasonable representations of zero would be exact.
If that is a concern, you could do:
select (case when try_convert(int, replace(col, '.', '')) = 0 then 1 else 0 end) as IsZero
Of course, this would allow 0.0.0.

Related

REPLACE to just have a number causing conversion failure

I'm trying to do a count to see how many fields in column value are > 10:
SELECT
COUNT(CASE WHEN t.value > 10)
THEN 1
ELSE NULL
END
FROM table t
WHERE t.DATE = '2017-01-01'
However, the column has a few custom entries like +15 or >14.0, so I added the following:
SELECT
COUNT(CASE WHEN value LIKE '>%'
and Replace(value, '>', '') > 10)
FROM table t
WHERE t.DATE = '2017-01-01'
However, after doing that, I get the following error:
Conversion failed when converting the varchar value '>14.0' to data
type int. Warning: Null value is eliminated by an aggregate or other
SET operation.
Seeing I have no access to rewrite the database with an UPDATE, does anyone have a workaround solution?
You could fix this, either by simply changing 10 to 10.0:
SELECT CASE WHEN '14.0' > 10.0 THEN 1 ELSE 0 END
This will cause the implicit conversion of '14.0' to decimal rather than int, which works, or you explicitly convert it:
SELECT CASE WHEN CONVERT(DECIMAL(14, 2), '14.0') > 10 THEN 1 ELSE 0 END
If it were me however, and I was not in a position to update the data, and do something a bit left field, like use a numeric data type to store numbers, I would ignore these values completely, and simply use TRY_CONVERT to avoid the conversion errors:
SELECT
COUNT(CASE WHEN TRY_CONVERT(DECIMAL(14, 2), value) > 10 THEN 1 END)
It is a varchar column, so the possibilities of what nonsense could be in there are endless, you might get a query that works now by replacing > and +, but then what about when someone puts in <, or ends up with a space in between like + 14, or something completely random like 'aaaa', where does it end?
It would be helpful to see the table and sample data, but it sounds like you have strings that are numbers and a sign.
You can cast it to convert the data since you are mixing and matching data types.
SELECT
COUNT(CASE WHEN CAST(value AS VARCHAR(10)) LIKE '>%'
and CAST(Replace(value, '>', '') AS your_num_datatype_here) > 10)

Datatype trouble in SQL Server 2008

I have a data something like this.
70.6
70.60
70.7
70.70
I can't use varchar as I need to perform arithmetic operations (>,< or floor), when I used float all records change to 70.7 and 70.6 from 70.70 and 70.60
When I changed to decimal(2,2), then all 70.6 records changed to 70.60.
Please suggest which data type suits for me.
Business need to retain 70.6 as it is and 70.60 as it is.
Currently data is in dataware house and stored in varchar.
I am preparing data mart and written query like
Result1 = CASE WHEN Dia = '' OR Dia > 28 OR M.Dia < 6 THEN 'Dia' END,
Result2 = CASE WHEN Width = '' OR Width > 16 OR M.Width < 3 THEN 'Width' END,
Result6 = CASE WHEN Bore] = '' OR FLOOR(LOG10(REVERSE(ABS(M.[Center Bore])+1)))+1 <> 2 THEN 'Bore' END,
From the mathematical point of view, there is no difference between 70.6 and 70.60. If your business rules must treat these values as different values, and you want to also be able to perform mathematical operations of them, you should keep them as decimal in your database, and I suggest adding a tinyint column that will specify the number of decimal digits of the original string value.
create a stored procedure that will get the value as string, calculate the number of decimal digits, convert the string to decimal, and save both of these values into the database.
When selecting the value you convert it to string and manipulate the decimal digits as you please.
You can use Convert(float, **) to convert the data from nvarchar.
I don't think there would be any difference can occur when your data is either 60.6 or 60.60 while performing arithmetic operation (>,< or floor)
select convert(float, '60.6') as val
Output: 60.6
as you mentioned in the comment
because I am checking data have only 1 digit after decimal
Then you can form get such a string using charindex and left.
select left(val, charindex('.', val) + 1) as new_val
from (select '60.6666' as val) as x
Input string : 60.6666
Output String : 60.6
now you can use
convert(float, new_val) as val
like,
select convert(float, left(val, charindex('.', val) + 1)) as val
from (select '60.6666' as val) as x

How do i check that in 100.00 number after decimal point is greater than 0 or not?

Actually I want to know that if number is 0.75 then consider it as value and if number is 75.00 then consider it as percentage and if number is 12.25 then also consider it as value
Modulus when divided by one will divide out the entire whole section and leave only the decimal remainder. try following:
SELECT CASE (100.00 % 1) WHEN 0 THEN 'Percent' ELSE 'Value' END
SELECT CASE (0.75 % 1) WHEN 0 THEN 'Percent' ELSE 'Value' END
One method is to convert to an integer and see if the original value matches. Your question is unclear on what you want the output to be, but perhaps:
select (case when value between 0 and 1 then 'value'
when cast(value as int) = value then 'percentage'
else 'value'
end)
Note: this is potentially not perfect because of inaccuracies in using floating point representations. It should work for decimal representations. Note also that 12.00001 is treated as a value rather than a percentage. Your question is quite unclear on what to do in this case. Most floating point representations store low-valued integers exactly, so this will work for exact matches.
If you only care about the first two decimal places, you can use the str() function or a double cast. For instance, for positive values:
select (case when value between 0 and 1 then 'value'
when right(str(value - floor(value as int), 10, 2), 2) = '00' then 'percentage'
else 'value'
end)

SQL Server: interpreting 'y' as BIT value

In C, when you compared true/false value to 1/0, it worked very well.
I would want the similar possibility with SQL Server - when I have a bit column, I would like to compare myBitField = 'y' / myBitField = 'n'
Is there anything I can do about that? Maybe change some SQL interpreter settings or something?
Example of what I would like to do:
select * from
(
select CAST(1 AS BIT) as result
) as main
where main.result = 'y'
Currently, it throws an error, and I would like it to return 1/true/'y', whatever, but I would like it to be able to make that comparison.
I suppose you want to do it for some yes/no thing. But this is generally a wrong concept, your application which is accessing the SQL Server should interpret y as a 1 and n as a 0 and afterwards set the correct parameters for the query. You should not (actually I'm temped to write "must not") do this in SQL Server, that's what you have a business logic for.
As others have said, BIT and CHAR / VARCHAR are entirely different datatypes. But if you want to cast them during the select, you can use CASE expression like so:
-- Reading string as BIT
SELECT CAST(CASE RESULT WHEN 'Y' THEN 1 WHEN 'N' THEN 0 ELSE NULL END AS BIT) RESULT
-- Reading BIT as string
SELECT CAST(CASE RESULT WHEN 1 THEN 'Y' WHEN 0 THEN 'N' ELSE NULL END AS CHAR(1)) RESULT
And that's about as far as your options go here, far as I can understand. :)

Why does the number 0 evaluate to a blank space

This is something that has baffled me before but I have never found an explanation for it. I have a column in a SQL Server 2008 database that is of type smallint. I want to look for any rows where the value is NULL or blank, so I say this:
SELECT *
FROM products
WHERE warranty_dom IS NULL
OR warranty_dom = ''
This returns rows with a value of 0
So why is 0 treated as the equivalent of '' ?
0 is not treated as '' per se. Instead, '' is implicitly cast to an integer, and that cast makes it 0.
Try it yourself:
SELECT CAST(0 AS varchar) -- Output: '0'
SELECT CAST('' AS smallint) -- Output: 0
Also, as mentioned elsewhere: If warranty_dom is of type smallint, then it's not possible for it to be blank in the first place.