Tricky substring usage in Oracle - string

I am looking for a way to retrieve always the 2 numbers after the last "/"character in a string. If there is something after the 2 numbers that I want, I don't care.
the code that I came up with is this:
CASE when INSTRUMENT like '%/%' then SUBSTR(INSTRUMENT,INSTR(INSTRUMENT,'/',-3,1)+1,2) else '0' end
This seems to work fine.
The problem is that when it does not find any "/"character, then it does not fill them with a 0 as I would like.
To give you an example of what I would like to perform:
XXX/YYY/ZZZ/92 ---> Returns 92
XXX/YYY/ZZZ/42 (test) ---> Returns 42
XXX YYY ZZZ 10 ---> Returns 0
All of this must be "plugged" in a select case statement, but this should not change the solution.
Thanks in advance

Perhaps regexp_substr will work for you. If it returns NULL, meaning the pattern of a slash followed by 2 digits and 0 or more characters to the end of the string was not found, replace with a '0' by using NVL().
SQL> with tbl(str) as (
select 'XXX/YYY/ZZZ/92' from dual union
select 'XXX/YYY/ZZZ/42 (test)' from dual union
select 'XXX YYY ZZZ 10' from dual
)
select nvl(regexp_substr(str, '/(\d{2}).*$', 1, 1, NULL, 1), '0') digits
from tbl;
DIGITS
---------------------
0
42
92
SQL>

Related

Remove 1-3 length character from string in sql

From a space delimited string, i would like to remove all words that are long from 1 to 3 characters.
For example: this string
LCCPIT A2 LCCMAD B JBPM_JIT CCC
should become
LCCPIT LCCMAD JBPM_JIT
So, A2, B and CCC words are removed (since they are long 2, 1 and 3 characters). Is there a way to do it? I think i could use REGEXP_REPLACE, but i didn't find the correct regular expression to have this result.
Split string to words and aggregate back only these substrings whose length is greater than 3.
Sample data:
SQL> with test (col) as
2 (select 'LCCPIT A2 LCCMAD B JBPM_JIT CCC' from dual)
Query begins here:
3 select listagg(val, ' ') within group (order by lvl) result
4 from (select regexp_substr(col, '[^ ]+', 1, level) val,
5 level lvl
6 from test
7 connect by level <= regexp_count(col, ' ') + 1
8 )
9 where length(val) > 3;
RESULT
--------------------------------------------------------------------------------
LCCPIT LCCMAD JBPM_JIT
SQL>
I prefer a regex replacement trick:
SELECT TRIM(REGEXP_REPLACE(val, '(^|\s+)\w{1,3}(\s+|$)', ' '))
FROM dual;
-- output is 'LCCPIT LCCMAD JBPM_JIT'
Demo
The strategy above is match any 1, 2, or 3 letter word, along with any surrounding whitespace, and to replace with just a single space. The outer call to TRIM() is necessary to remove dangling spaces which might arise from the first or last word being removed.

replace value in a string with different values where the string changes

I have a 5 character code that needs to be converted to a 4 character code. Additionally, the 5th character is either a 1, 2 or 5, and I need to convert them to 1, 5 or 9. As an example, if my query returns '20155', I need to translate that to '2159'. So far I have:
select substr(fieldname,1,1) || substr(fieldname,3,2) || substr(fieldname,-1,1) as newfieldname
This converts it from 5 to 4 characters. What I don't know how to do is also change the last character to the new value as described above.
A sample of what I want it to achieve is:
20141 becomes 2141
20142 becomes 2145
20145 becomes 2149
20151 becomes 2151
20152 becomes 2155
20155 becomes 2159
Any assistance would be appreciated. I am not a computer programmer - I am a functional analyst that has to validate over 500,000 rows of data, each row containing the fieldname above.
You can use "case when ":
Case when 2 then 5 , etc...

IF, ELSE function gives wrong result

my If else statelement is :
=IF(AC2<0,5;"0";IF(AC2<1,5;"1";IF(AC2<2,5;"2";"3")))
and AC is a column containing multiple values .
For example : AC2 value is : 2,27 the result should be 2 but i am getting 3 as a result and AC3 value is 0;83 and i get also 3 as result.
Conclusion : i am getting 3 as a result for all columns, it doesn't test all the IF but jumps directly into the ELSE statement.
You have inverted commas ("") which turns you're 1, 2 and 3 from numbers to text - as mentioned in the comments, there's an easier formula - =round(AC2,0) which will round as you're doing (and goes on to 4.5, 5.5 etc..)

Validate table for empty cells

Could you help to advise some script to validate a table cells for empty values? I need to validate that there are no empty cells in table.
tableFG = page.table(:id => 'FinancialsGrid')
tableFG.rows.each do |row|
row.cells.each do |cell|
expect(cell.tableFG_element.text).should_not be_nil
end
end
May be there is another way to check for empty values.
The one thing I do not like about manually writing a loop to iterate through and validate each cell is that you only see the result of the first failure. If there are say two cells that are blank, the test failure will only show one.
As a result, I try to make use of the built-in expectation matchers that check each element (ex all). For example, the following gets the length of text of each cell and makes sure that it is at least 1 character long. Note that Watir strips leading/trailing whitespaces, so a length of 1 should be an actual character.
financials_grid = browser.table(:id => 'FinancialsGrid')
expect(financials_grid.tds.map(&:text).map(&:length)).to all( be > 0 )
A failed expectation would look like the following and include each cell that fails:
expected [1, 0, 0, 1] to all be > 0
object at index 1 failed to match:
expected: > 0
got: 0
object at index 2 failed to match:
expected: > 0
got: 0
Using the page-object gem would be similar (with slightly different methods). Assuming the table is defined in the page as the financials_grid:
page = MyPage.new(browser)
expect(
page.financials_grid_element.cell_elements.map(&:text).map(&:length)
).to all( be > 0 )

Oracle extract variable number from string

I'm looking to extract a specific number out of a string of mixed alphanumeric characters that are variable in length in a query. I will need this in order to calculate a range based off that number. I'm using Oracle.
Example:
D-3-J32P232
-I need to grab the J32 at least, and most likely even the 32 out of that string. This range of numbers can change at any given time.
It could range from:
D-3-J1P232
to
D-3-J322P2342
The numbers after the second and third letters can be any number of length. Is there any way to do this?
This is simpler and gets both the numbers for the range
select substr( REGEXP_SUBSTR('D-3-J322P2342','[A-Z][0-9]+',1,1),2),
substr( REGEXP_SUBSTR('D-3-J322P2342','[A-Z][0-9]+',1,2),2)
from dual
REGEXP_SUBSTR could work (11g version):
SELECT REGEXP_SUBSTR('D-3-J322P2342','([A-Z]+-\d+-[A-Z]+)(\d+)',1,1,'i',2) num
FROM dual;
A test of your sample data:
SQL> SELECT REGEXP_SUBSTR('D-3-J322P2342',''([A-Z]+-\d+-[A-Z]+)(\d+)',1,1,'i',2) num
2 FROM dual;
NUM
---
322
SQL>
This will accept any case alpha string, followed by a dash, followed by one or more digits, followed by a dash, followed by another any case alpha string, then your number of interest.
In 10g REGEXP_REPLACE, it's bit less straightforward, as they did not add the ability to reference subexpressions until 11g:
SELECT REGEXP_SUBSTR(str,'\d+',1,1) NUM
FROM (SELECT REGEXP_REPLACE('D-3-J322P2342','([A-Z]+-\d+-[A-Z]+)','',1,1,'i') str
FROM dual);
Your sample data:
SQL> SELECT REGEXP_SUBSTR(str,'\d+',1,1) NUM
2 FROM
(SELECT REGEXP_REPLACE('D-3-J322P2342','([A-Z]+-\d+-[A-Z]+)','',1,1,'i') str
3 FROM dual);
NUM
---
322
REGEXP_SUBSTR would do the job

Resources