How can I use RTRIM or REPLACE when I know the length I want to trim but not what it may contain? - sql

I need to RTRIM the last 7 characters from a result set in an Oracle query. These 7 chars can be anything; spaces, alpha numeric etc... and I don't know the exact length of any value.
So for example I'd like to run something like this
SELECT RTRIM (COl_A, (SELECT LENGTH (COL_A)-7) FROM TABLE_ONE;
or a replace equivalent
SELECT REPLACE(COL_A, (SELECT LENGTH (COL_A)-7 FROM TABLE_ONE),'');
Do I need to do something with SUBSTRING maybe?
I know how to remove/replace specific chars but I'm having trouble when dealing with unknown chars. I've seen a few examples of similar problems but they seem unnecessarily complicated... or does this require a more in depth solution than I think it should?
As always thanks in advance for advice or hints.

You are in search of the substr function.
select substr(col_a, 1, length(col_a) - 7) from table_one

Actually, the correct solution is:
select substr(col_a, 1, (case when length(col_a) < 7 then 0 else length(col_a) - 7 end) from table_one
To be general, you would want to take into account what happens when the length is less than 7.

Related

Sort a VARCHAR column in SQL Server that contains numbers?

I have a column in which data has letters with numbers.
For example:
1 name
2 names ....
100 names
When sorting this data, it is not sorted correctly, how can I fix this? I made a request but it doesn’t sort correctly.
select name_subagent
from Subagent
order by
case IsNumeric(name_subagent)
when 1 then Replicate('0', 100 - Len(name_subagent)) + name_subagent
else name_subagent
end
This should work
select name_subagent
from Subagent
order by CAST(LEFT(name_subagent, PATINDEX('%[^0-9]%', name_subagent + 'a') - 1) as int)
This expression will find the first occurrence of a letter withing a string and assume anything prior to this position is a number.
You will need to adapt this statement to your needs as apparently your data is not in Latin characters.
With a bit of tweaking you should be able to achieve exactly what you're looking for:
select
name_subagent
from
Subagent
order by
CAST(SUBSTRING(name_subagent,0,PATINDEX('%[A-Z]%',name_subagent)) as numeric)
Note, the '%[A-Z]%' expression. This will only look for the first occurrence of a letter within the string.
I'm not considering special characters such as '!', '#' and so on. This is the bit you might want to play around with and adapt to your needs.

substring with variable last character SQL Server

I have a number of rows in a database column that look like this
AB01-52
AB01-52/1
AB01-53/2
AB01-54
I can get the 52 where there is no slash in the string but when I try to get it between the dash and the slash I either get an error or get the 52/1 for example
I have tried most of the researched solutions using substring and charindex but to no avail
Has anyone seen a solution for this.
Thanks in advance
Rick
You can subtract the characters positions (i.e. /) and use as length for substring()
substring(col, charindex('-', col)+1, len(col)-charindex('/', col)+1)
If the numbers have variable length then do the subtraction from both characters and use of length
substring(col, charindex('-', col)+1, charindex('/', col+'/')-charindex('-', col)-1)
Here's one approach....
with cte as(
select 'AB01-53/2' as C1
union
select 'AB01-54')
select left(right(c1,len(c1) - charindex('-',c1)),len(right(c1,len(c1) - charindex('-',c1))) - charindex('/',right(c1,len(c1) - charindex('-',c1)))+ 1)
from cte
If the field is ALWAYS AAAA-BB[/CCC], then simply:
SUNSTRING('AB01-52/1',6,2) ;
Of course, the 'AB01-52/1' may be substituted by a variable or column name.
I may have found an answer but it involves a 2 stage process
First add an additional slash to the column that contains the data where there is no slash at the moment ie AB01-52 becomes AB01-52/ the others like AB01-1023/01 remain the same
stage 2 use this code:
substring(right(col1,len(col1)-charindex('-',col1)),0,charindex('/',right(col1,len(col1)-charindex('-',col1))))
this allows me to get the middle string. The use of left and right by various people who contributed helped to get to this - however I still thing there should be an answer without stage 1
Thanks you all for your ideas which got me to this point

REGEXP_SUBSTR to extract fixed length string starting from a digit

Table A
ID ID_Descr
1 'DUP 8002061286'
2 'DUP 8002082667 '
3 ' 8002082669 DUP'
I would like to extract the string from the ID_Descr field with the following conditions:
String always starts with 8
String length is always 10 digits
This means stripping everything to the right and left of the string (eg. '8002082669'). How can I achieve this? Using REGEXP_SUBSTR?
I am using Oracle 11g.
Thanks!
Although you could use regexp_substr() for this, I would take a different approach. I would just look for the '8' using instr() and then take the next 10 characters:
select substr(id_descr, instr(id_descr, '8'), 10)
This seems like the simplest solution.
You could use REGEXP_SUBSTR() but a regex is an expensive operation so you would be much better off using SUBSTR() and INSTR():
SELECT SUBSTR(ID_Descr, INSTR(ID_Descr, '8'), 10) FROM tableA;
If you really wanted to use REGEXP_SUBSTR() you could do it as follows:
SELECT REGEXP_SUBSTR(ID_Descr, '8.{9}') FROM tableA;
This would get 8 plus the following 9 characters (. being the wildcard).
Now if you wanted to match only digits, then REGEXP_SUBSTR() would probably be your best bet:
SELECT REGEXP_SUBSTR(ID_Descr, '8[0-9]{9}') FROM tableA;

Get rows that contain only certain characters

I want to get only those rows that contain ONLY certain characters in a column.
Let's say the column name is DATA.
I want to get all rows where in DATA are ONLY (must have all three conditions!):
Numeric characters (1 2 3 4 5 6 7 8 9 0)
Dash (-)
Comma (,)
For instance:
Value "10,20,20-30,30" IS OK
Value "10,20A,20-30,30Z" IS NOT OK
Value "30" IS NOT OK
Value "AAAA" IS NOT OK
Value "30-" IS NOT OK
Value "30," IS NOT OK
Value "-," IS NOT OK
Try patindex:
select * from(
select '10,20,20-30,30' txt union
select '10,20,20-30,40' txt union
select '10,20A,20-30,30Z' txt
)x
where patindex('%[^0-9,-]%', txt)=0
For you table, try like:
select
DATA
from
YourTable
where
patindex('%[^0-9,-]%', DATA)=0
As per your new edited question, the query should be like:
select
DATA
from
YourTable
where
PATINDEX('%[^0-9,-]%', DATA)=0 and
PATINDEX('%[0-9]%', LEFT(DATA, 1))=1 and
PATINDEX('%[0-9]%', RIGHT(DATA, 1))=1 and
PATINDEX('%[,-][-,]%', DATA)=0
Edit: Your question was edited, so this answer is no longer correct. I won't bother updating it since someone else already has updated theirs. This answer does not fulfil the condition that all three character types must be found.
You can use a LIKE expression for this, although it's slightly convoluted:
where data not like '%[^0123456789,!-]%' escape '!'
Explanation:
[^...] matches any character that is not in the ... part. % matches any number (including zero) of any character. So [^0123456789-,] is the set of characters that you want to disallow.
However: - is a special character inside of [], so we must escape it, which we do by using an escape character, and I've chosen !.
So, you match rows that do not contain (not like) any character that is not in your disallowed set.
Use option with PATINDEX and LIKE logic operator
SELECT *
FROM dbo.test70
WHERE PATINDEX('%[A-Z]%', DATA) = 0
AND PATINDEX('%[0-9]%', DATA) > 0
AND DATA LIKE '%-%'
AND DATA LIKE '%,%'
Demo on SQLFiddle
As already mentioned u can use a LIKE expression but it will only work with some minor modifications, otherwise too many rows will be filtered out.
SELECT * FROM X WHERE T NOT LIKE '%[^0-9!-,]%' ESCAPE '!'
see working example here:
http://sqlfiddle.com/#!3/474f5/6
edit:
to meet all 3 conditions:
SELECT *
FROM X
WHERE T LIKE '%[0-9]%'
AND T LIKE '%-%'
AND T LIKE '%,%'
see: http://sqlfiddle.com/#!3/86328/1
Maybe not the most beautiful but a working solution.

How to get rightmost 10 places of a string in oracle

I am trying to fetch an id from an oracle table. It's something like TN0001234567890345. What I want is to sort the values according to the right most 10 positions (e.g. 4567890345). I am using Oracle 11g. Is there any function to cut the rightmost 10 places in Oracle SQL?
You can use SUBSTR function as:
select substr('TN0001234567890345',-10) from dual;
Output:
4567890345
codaddict's solution works if your string is known to be at least as long as the length it is to be trimmed to. However, if you could have shorter strings (e.g. trimming to last 10 characters and one of the strings to trim is 'abc') this returns null which is likely not what you want.
Thus, here's the slightly modified version that will take rightmost 10 characters regardless of length as long as they are present:
select substr(colName, -least(length(colName), 10)) from tableName;
Another way of doing it though more tedious. Use the REVERSE and SUBSTR functions as indicated below:
SELECT REVERSE(SUBSTR(REVERSE('TN0001234567890345'), 1, 10)) FROM DUAL;
The first REVERSE function will return the string 5430987654321000NT.
The SUBSTR function will read our new string 5430987654321000NT from the first character to the tenth character which will return 5430987654.
The last REVERSE function will return our original string minus the first 8 characters i.e. 4567890345
SQL> SELECT SUBSTR('00000000123456789', -10) FROM DUAL;
Result: 0123456789
Yeah this is an old post, but it popped up in the list due to someone editing it for some reason and I was appalled that a regular expression solution was not included! So here's a solution using regex_substr in the order by clause just for an exercise in futility. The regex looks at the last 10 characters in the string:
with tbl(str) as (
select 'TN0001239567890345' from dual union
select 'TN0001234567890345' from dual
)
select str
from tbl
order by to_number(regexp_substr(str, '.{10}$'));
An assumption is made that the ID part of the string is at least 10 digits.