How do I return a value if the string is between 6 and 10 characters in SQL? - sql

I have a column of data where the length of each entry varies, e.g
12345678
123
AA
12345678912345
......
I wish to return value if the string length is between 6 and 10. If it's less than 6 or greater than 10, then return a blank.
In my example I would have one value 12345678 showing and three blanks.

You can use LEN function to test length of column value and CASE to return the value you want (supposing the column name is "field"):
SELECT CASE WHEN (LEN(field) >= 6 AND LEN(field) <= 10)
THEN field
ELSE '' END as 'YourField'
FROM nameoftable

To get it without the blanks you would do:
SELECT FIELD
FROM table_name
WHERE LEN(FIELD) >= 6 AND LEN(FIELD) <= 10

If you don't mind having the output for each row presented in a new column, you could do the following:
Assume the data you have is stored in "colA" in a table called "yourTable", then:
select case when len(colA) between 6 and 10 then colA else '' end as colB from yourTable
The syntax above will work in Microsoft SQL Server. You may have to tweak to find the equivalent length and comparison functions in whichever RDMS you happen to be using.
Another issue you may face is data type conversion issues. If your colA is defined as a character field, the code above should work without issue (i.e., you'll get blanks back for values outside of your test criteria). If colA is numeric, then using '' to insert a blank may actually return 0. It's up to you to decide how you want to handle this issue.

Related

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}$'

Prevent ORA-01722: invalid number in Oracle

I have this query
SELECT text
FROM book
WHERE lyrics IS NULL
AND MOD(TO_NUMBER(SUBSTR(text,18,16)),5) = 1
sometimes the string is something like this $OK$OK$OK$OK$OK$OK$OK, sometimes something like #P,351811040302663;E,101;D,07112018134733,07012018144712;G,4908611,50930248,207,990;M,79379;S,0;IO,3,0,0
if I would like to know if it is possible to prevent ORA-01722: invalid number, because is some causes the char in that position is not a number.
I run this query inside a procedure a process all the rows in a cursor, if 1 row is not a number I can't process any row
You could use VALIDATE_CONVERSION if it's Oracle 12c Release 2 (12.2),
WITH book(text) AS
(SELECT '#P,351811040302663;E,101;D,07112018134733,07012018144712;G,4908611,50930248,207,990;M,79379;S,0;IO,3,0,0'
FROM DUAL
UNION ALL SELECT '$OK$OK$OK$OK$OK$OK$OK'
FROM DUAL
UNION ALL SELECT '12I45678912B456781234567812345671'
FROM DUAL)
SELECT *
FROM book
WHERE CASE
WHEN VALIDATE_CONVERSION(SUBSTR(text,18,16) AS NUMBER) = 1
THEN MOD(TO_NUMBER(SUBSTR(text,18,16)),5)
ELSE 0
END = 1 ;
Output
TEXT
12I45678912B456781234567812345671
Assuming the condition should be true if and only if the 16-character substring starting at position 18 is made up of 16 digits, and the number is equal to 1 modulo 5, then you could write it like this:
...
where .....
and case when translate(substr(text, 18, 16), 'z0123456789', 'z') is null
and substr(text, 33, 1) in ('1', '6')
then 1 end
= 1
This will check that the substring is made up of all-digits: the translate() function will replace every occurrence of z in the string with itself, and every occurrence of 0, 1, ..., 9 with nothing (it will simply remove them). The odd-looking z is needed due to Oracle's odd implementation of NULL and empty strings (you can use any other character instead of z, but you need some character so no argument to translate() is NULL). Then - the substring is made up of all-digits if and only if the result of this translation is null (an empty string). And you still check to see if the last character is 1 or 6.
Note that I didn't use any regular expressions; this is important if you have a large amount of data, since standard string functions like translate() are much faster than regular expression functions. Also, everything is based on character data type - no math functions like mod(). (Same as in Thorsten's answer, which was only missing the first part of what I suggested here - checking to see that the entire substring is made up of digits.)
SELECT text
FROM book
WHERE lyrics IS NULL
AND case when regexp_like(SUBSTR(text,18,16),'^[^a-zA-Z]*$') then MOD(TO_NUMBER(SUBSTR(text,18,16)),5)
else null
end = 1;

How to implement MAX function on a text column in SQL Server?

I'm using SQL Server 2005 and have a column that contains serial numbers, which are nvarchar(50).
My problem is selecting max(serial_no) from the table. The serial numbers used to have a length of 7 only but new ones are now 15. Whenever I select the max, I get a result with a length of 7, which means that data is old. I also can't filter it to only select from records which have a length of 15 because then i'll miss some other data on my query.
Old serial numbers look like this...
'SNGD001'
..., and new ones look like this:
'SN14ABCD0000001'
Edit: I tried creating a dummy table without the old serial numbers (5 characters long), and I'm getting correct results.
As has been mentioned, your question is a bit hard to follow. If the max value could be either one of your old serial numbers or one of your new ones, I believe the following should do the trick:
SELECT MAX(RIGHT('0000000' + REVERSE(LEFT(REVERSE(YourTextColumn), PATINDEX('%[a-z]%', REVERSE(YourTextColumn)) - 1)), 7))
FROM YourTable
It finds the first non numeric character from the right keeping everything to the right of that. It then left zero pads the resulting numeric string to 7 characters and applies the MAX function.
Your question is a little tough to follow without good sample data to get a bearing on. I suggest for future, you show a few more examples of data to get better context, especially with sequencing. Now, your desire to get the MAX() of a "serial_no" from your table appears you need so you get detect the next sequential serial number to assign. However, your serial number appears to be a concatenation of a prefix string and then sequential. So, if I were to look at your brief data MIGHT HAVE BEEN along the lines of (last 3 digits are the sequential serializations)
SNGD001
SNGD002
SNGD003
...
SNGD389, etc...
and your new data with the last (last 7 digits are sequential serializations)
SN14ABCD0000001
SN14ABCD0000002
SN14ABCD0000003
...
SN14ABCD0002837
If this is correct, then you basically need to look at the max based on the leading 3 or 8 characters of the string PLUS the converted suffix numeric sequence. For starters, lets go with that to see if we are on the correct track or not, then you can easily concatenate the prefix and sequence number together at the end for determining the next available number.
So, based on the above samples, you may want to know that for each prefix, the last number of
SNGD389 and
SN14ABCD0002837 respective per their prefix
If the above is correct, I might start with...
select
case when LEN( RTRIM( yt.serial_no )) = 7
then LEFT( yt.serial_no, 4 )
else LEFT( yt.serial_no, 8 ) end as SerialPrefix,
MAX( case when LEN( RTRIM( yt.serial_no )) = 7
then CONVERT(INT, RIGHT( yt.serial_no, 3 ))
else CONVERT(INT, RIGHT( yt.serial_no, 7 )) end ) as SerialSequence
from
YourTable yt
group by
case when LEN( RTRIM( yt.serial_no )) = 7
then LEFT( yt.serial_no, 4 )
else LEFT( yt.serial_no, 8 ) end as SerialPrefix
Which would result in (based on sample data I presented)
SerialPrefix SerialSequence
SNGD 389
SN14ABCD 0002837
Of which since the serial sequence column being numeric, you could add 1 to it, then left-zero fill a string and concatenate the two back together such as to create
SNGD390
SN14ABCD0002838

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.

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