Sql parse column as int and check if it is within range - sql

I've used the top voted answer from here to check if a cell value is an integer. But I also need to do a range check on it.
SELECT * FROM Table
WHERE (dbo.IsInteger(FieldName) = 1) AND FieldName > 400 AND FieldName < 500
But this returns a conversion error, as some of the cells in the column contains text. So, is it possible to get a subset, that is only results from the IsInteger query, and then do a range check on the result?

You need to wrap it in a CASE expression. I've altered the query slightly to use BETWEEN to avoid having to repeat the expression.
SELECT * FROM Table
WHERE CASE WHEN dbo.IsInteger(FieldName) = 1
THEN FieldName END BETWEEN 401 AND 499
The result of the expression will be NULL when dbo.IsInteger(FieldName) <> 1 which will not match the BETWEEN predicate.
Of course this is completely unsargable but so is your original query.

Related

Replace a range of values in an SQL table to a single value

I am trying to replace a range of values with a string. I know how to do it with the replace function but that, as far as I know, requires them to be done one at a time.
Is there a way to select a range of values, for example (1-200), and replace them with a singular string value say "BLANK"?
I have tried WHEN, THEN and SET but get a syntax error near WHEN or SET as I try these.
Base Code Idea
Select DATA
WHEN DATA >= 1 THEN 'BLANK'
WHEN DATA <200 THEN 'BLANK
END
FROM DATABANK
Thanks!
Is this what you want?
select data,
case when data not between 1 and 200 then data end as new_data
from databank
What this does is take the integer value of data, and replace any value that's in the 1-200 range with null values, while leaving other values unchanged. The result goes into column new_data.
The assumption here is that data is a number - so the alternative value has to be consistent with that datatype (string 'BLANK' isn't): I went for null, which is consistent with any datatype, and is the default value returned by a case expression when no branch matches.
If you wanted something else, say 0, you would do:
select data,
case when data between 1 and 200 then 0 else data end as new_data
from databank

why 'select (0 < 1)' does not work in Sql Server?

If I let MySQL execute SELECT (0 < 1), it return 1; But if I run this select statement with SQL Server, it give me an error:
Incorrect syntax near '<'.
I also have tested other operator like != and <, and get the same error. I'm confused. '0 < 1' is an expression, why can't SQL Server evaluate it?
This behavior is by design:
Unlike other SQL Server data types, a Boolean data type cannot be
specified as the data type of a table column or variable, and cannot
be returned in a result set.
[...]
Expressions with Boolean data types are used in the WHERE clause to
filter the rows that qualify for the search conditions and in
control-of-flow language statements such as IF and WHILE
So Boolean datatype exists, you just cannot use it outside WHERE clause (etc).
The correct SQL Server equivalent of MySQL SELECT x < 1 (which returns 0, 1 or NULL) would be:
SELECT CASE
WHEN x < 1 THEN 1
WHEN NOT (x < 1) THEN 0
ELSE NULL -- you can omit this line
END
Finally, LEN(NULL) is NULL and (generally speaking) any operation on NULL yields NULL. So the condition IF LEN(NULL) < 1 will not execute, neither will IF LEN(NULL) >= 1.
MS SQL doesn't have a boolean type. It supports boolean expressions, but those cannot be values in variables or result sets.
The best you can do is something like
select case when 0 < 1 then 0 else 1 end
The result set will have a normal integer (the bit type is sometimes used to represent true/false values, but it's just a number with possible values of 1 and 0).
I'm confused. '0 < 1' is an expression, why can't SQL Server evaluate it?
It sort of is and sort of isn't. It's a predicate, and SQL Server treats predicates differently from other expressions which produce values.
SQL Server doesn't have a user-visible boolean data type so you cannot write an expression that produces a value of this non-existent data type.
You can only use predicates in specific positions, such as the WHERE clause, ON clauses, WHEN clauses (part of a CASE expression) and CHECK constraints (there are others)

Changing value of a temporary table based on condition

I am using amazon redshift and I need to change values for a column called 'codes' in a temporary table like below.
id code
--- ----
1 99990
2 A0002
3 0000F
I need to check if the first and last character is numeric , if they both are then change the column value based on its range (e.g set code = 'category1' when 90000 < code < 99999).
If the last character is an alphabet, then set the code based on the range of the first 4 characters (e.g set code = "category2" when 0 < code[:4] < 1000 )
What I have right now is :
UPDATE tmp_table
SET code = 'category1'
WHERE substring(code,1,1) ~ '[0-9]'
AND 90000 <= CONVERT(INT,code) <= 99999 ;
However I am getting error for code like 'A0002' , the error message is : Invalid operation, Invalid digit, Value 'A'.
I suspect the reason is when it fails the first condition , and inside the second condition, the convert function can not take in non-numeric value thus raising the error. But I am not sure how to fix this and get what I want.
Any suggestions ? Thanks
The order of evaluation of expressions is indeterminate. They can be evaluated in any order.
To fix this, use case:
UPDATE tmp_table
SET code = 'category1'
WHERE (CASE WHEN code ~ '[0-9]+'
THEN CONVERT(INT, code) BETWEEN 90000 AND 99999
END);
Or, forget the conversion and just use string logic:
WHERE CODE ~ '^9[0-9]{4}$'

SQL server casting string to integer checking value before casting

I have a table with a field named MINIMUM_AGE. The values stored in this field are of type nvarchar:
17 years
54 years
N/A
65 years
I would like to apply a WHERE clause on the column to check for a certain age range. To do that I need to parse out the age from the field values.
So, I think I need to select the first two characters, then cast them into an integer. Also, some fields may not contain numbers for the first two characters. Some may simply be N/A. So, I will need to check for that before casting.
Can someone explain how to accomplish this?
Here is the SQL Fiddle that demonstrates the below query:
SELECT CASE
WHEN MINIMUM_AGE <> 'N/A'
THEN CAST(LEFT(MINIMUM_AGE, 2) AS int)
ELSE 0
END
FROM MyTable
Note: the CASE expression can only return one data type. So, in the example above if the MINIMUM_AGE is N/A then it returns 0.
If you would rather have it return null, then use the following:
SELECT CASE
WHEN MINIMUM_AGE <> 'N/A'
THEN CAST(LEFT(MINIMUM_AGE, 2) AS int)
END
FROM MyTable

Need to find value in one column and then return value from another column

Here is my problem. I have a Microsoft SQL server database table with a bunch of columns in it. (I cannot change the data structure of this table!)
21 of the columns in this table stand for 'Actual' sizes
21 of the columns in this table stand for 'Relative' sizes
The Actual size columns correspond through Relative size columns via column number. (ex : ActualColumn1 corresponds to RelativeColumn1, ActualColumn2 corresponds to RelativeColumn2, ActualColumnX to RelativeColumnX up to 21)
Based on the inputted 'Actual' value I need to return the related 'Relative' value.
I have managed to do part of what I need with the following case statement, but case statements have a maximum of 10 conditions and therefore won't be able to cover all 21 columns in my table. What would be the best way to approach this issue? My goal would be to put this into a select statement so that I could select the Relative Size and return it in my query.
Example of what I did with the case statement:
SELECT
T.AValue
CASE WHEN (T.ActualColumn1 = T.AValue) then T.RelativeColumn1 ELSE
CASE WHEN (T.ActualColumn2 = T.AValue) THEN T.RelativeColumn2 ELSE
CASE WHEN (T.ActualColumn3 = T.AValue) THEN T.RelativeColumn3 ELSE
CASE WHEN (T.ActualColumn4 = T.AValue) THEN T.RelativeColumn4 ELSE
NULL
END
END
END
END AS RValue
FROM T
Thank you for your help!
If you change your case statement to a searched case you can have more then 10 when clauses.
select T.AValue,
case T.AValue
when T.ActualColumn1 then T.RelativeColumn1
when T.ActualColumn2 then T.RelativeColumn2
when T.ActualColumn3 then T.RelativeColumn3
when T.ActualColumn4 then T.RelativeColumn4
end as RValue
from T