REMOVE THE LAST COMMA in oracle - oracle

COUNTNUM is a column name in a table that has data like below
1,2,3,4,
I used
RTRIM((COUNTNUM),',') COUNTNUM
It didn't work
Desired output
1,2,3,4
Current output
1,2,3,4,
Any suggestions would greatly help..!
Thanks

REGEXP_REPLACE((countnum), ',$', '')

Perhaps There are non-digits after the comma which needed to be removed
Logic is added to account for possible non-digits between the comma and the end of countnum.
Explanation:
[^[:digit:]] is the negation of the digit character class
* is a quantifier meaning zero to many
$ is an anchor identify the end of countnum
SCOTT#dev>WITH d AS (
2 SELECT
3 '1,2,3,4, ' countnum
4 FROM
5 dual
6 UNION ALL
7 SELECT
8 '1,2,3,4,'
9 FROM
10 dual
11 ) SELECT
12 countnum,
13 regexp_replace(
14 countnum,
15 ',[^[:digit:]]*$'
16 ) mod_count_num
17 FROM
18 d;
COUNTNUM MOD_COUNT_NUM
1,2,3,4, 1,2,3,4
1,2,3,4, 1,2,3,4

Related

How to break a VARCHAR2(4000) string line in Multiple Rows Counting the Words Repetition

I have an Issues DataBase, with many solutions open/closed for each issue in a view.
My chalenge is take all the answers, break it in each words it as was writed, and count these words separeted by column for the entire number of issues stored in this Data Base (view).
Sample.:
SELECT * FROM VW_ISSUE_REPORT;
issueID
ProblemReported
Solution
IsClosed
1
Printer Offline
Turn On the Printer ABC
Yes
2
Printer Paper Jam
Remove Paper Jam from Printer ABC
No
Result expected: (This is a historical database, I can't create functions, procedures, etc. Just a smart, and well known SELECT statement.).
SELECT MAGIC_SOLUTION( Solution) AS SolutionKeyWord , COUNT('X') AS SolutionRepetitions FROM VW_ISSUE_REPORT GROUP BY MAGIC_SOLUTION( Solution);
SolutionKeyWord
SolutionRepetitions
ABC
2
Printer
2
from
1
Jam
1
On
1
Paper
1
Remove
1
the
1
Turn
1
Best Regards
As you can't (at least, I think you can't) distinguish "names" from "solutions" (i.e. how to remove "ABC" from result? It can be anything, from HP to Canon to its IP address), one option is to split the whole solution into rows and count how many times each of its words repeats.
Sample data:
SQL> with test (issue_id, problemreported, solution, isclosed) as
2 (select 1, 'Printer Offline', 'Turn On the Printer ABC', 'Yes' from dual union all
3 select 2, 'Printer Paper Jam', 'Remove Paper Jam from Printer ABC', 'No' from dual
4 )
Query begins here:
5 select regexp_substr(solution, '[^ ]+', 1, column_value) solution_keyword,
6 count(*) solution_repetitions
7 from test cross join
8 table(cast(multiset(select level from dual
9 connect by level <= regexp_count(solution, ' ') + 1
10 ) as sys.odcinumberlist))
11 group by regexp_substr(solution, '[^ ]+', 1, column_value);
SOLUTION_KEYWORD SOLUTION_REPETITIONS
--------------------------------- --------------------
Paper 1
Printer 2
Turn 1
the 1
Remove 1
Jam 1
On 1
from 1
ABC 2
9 rows selected.
SQL>

Need specific number format in Oracle S9(15)V9(2)

I have a requirement to produce amount fields in zoned decimal format with this specific syntax below.
I don’t know if I need to create a function to handle this or if I can tweak the Oracle number format model. I’m thinking it might require some conditional formatting within a function due to the different requirement for number of digits between positive and negative. I will be performing this formatting on a couple of dozen data elements in the procedure so that might be another reason to use a function. Thoughts?
Requirement:
Amount should be represented by 17 characters (positive number) or 16 characters plus a “}” appended to the end (negative number).
Ex. 0.00 should show as 00000000000000000.
Ex. -935,560.00 should show as 00000000093556000}
Using Oracle 12c.
If I understood you correctly, the input is already formatted and its datatype is VARCHAR2. If that's so, then this might do the job:
SQL> with test (col) as
2 (select '0.00' from dual union all
3 select '25.34' from dual union all
4 select '-935,560.00' from dual
5 )
6 select col,
7 lpad(translate(col, 'x,.-', 'x'),
8 case when substr(col, 1, 1) = '-' then 16
9 else 17
10 end, '0') ||
11 case when substr(col, 1, 1) = '-' then '}'
12 else null
13 end result
14 from test;
COL RESULT
----------- --------------------
0.00 00000000000000000
25.34 00000000000002534
-935,560.00 0000000093556000}
SQL>
What does it do?
lines #1 - 5 - sample data
line #7 - translate removes minus sign, commas and dots
lines #7 - 10 - lpad pads the number (without characters from the previous step) with zeros up to the length of 16 (for negative values) or 17 (for positive values) characters
lines #11 - 13 - if it is a negative value, concatenate } to the end of the result string

How to use different group separators for thousands and millions. Oracle

I need to display different results in the next format, example:
40000000 to 40'000,000
I tried using this, but when i try 2 differents group separators i get the "invalid number format model" error:
select to_char(9999999999, '9g999g99999g9', 'NLS_NUMERIC_CHARACTERS='',.''')
from dual;
Also tried using substr and replace but it doesnt work in all the cases (like when the result is 3000000 or 700000000).
This works but it is not the optimal solution.:
SELECT substr(replace('40,000,000',',',''''),0,length(40000000)-2)|| substr('40,000,000',-4) from dual;
What the actual select look like if i use the previous code.
SELECT substr(replace(to_char(oTOTAL_SENIOR, '999,999,999'),',',''''),0,length(oTOTAL_SENIOR)-2)|| substr(to_char(oTOTAL_SENIOR, '999,999,999'),-4) from dual
The previous select gets bugged when i use substr replace and to_char together because of the '999,999,999'.
I also tried using regexp_replace but im not good at it.
I know i need to replace everything but the last 4 characters (,000) but i dont know how.
Any help will be aprreciated.
You'll need someone smarter than me to do that properly, but - meanwhile, see whether this helps.
I'm on XE 11g; in order to avoid "no more data to read from socket" error I got during the final steps of this query (I believe it was due to two string reversings), I created my own "reverse" function. There's undocumented reverse function, but I don't want to use it.
Basically, it reverses a string you pass as a parameter. What do I need it for? I found it simpler to reverse values, split them to 3-by-3-by-3 characters and apply those "strange" separators you want. Also, it makes the whole code simpler. It can be done without it, but - as I said - no more data to read from socket won't allow it. Sorry about that.
Now, someone will say: why didn't you (meaning: me, LF) do that using PL/SQL completely and put everything into a function? No particular reason & no problem in doing it, if necessary.
OK, here it is:
SQL> create or replace function f_reverse (par_string in varchar2)
2 return varchar2
3 is
4 retval varchar2(20);
5 begin
6 select listagg(substr(par_string, level, 1))
7 within group (order by level desc)
8 into retval
9 from dual
10 connect by level <= length(par_string);
11
12 return retval;
13 end;
14 /
Function created.
SQL> select f_reverse('1234') from dual;
F_REVERSE('1234')
---------------------------------------------------------------------
4321
SQL>
Finally, this is what you want:
SQL> with test (id, col) as
2 (select 1, 40100200 from dual union all
3 select 2, 2300400 from dual union all
4 select 3, 700500 from dual union all
5 select 4, 25700 from dual union all
6 select 5, 6300 from dual union all
7 select 6, 555 from dual
8 )
9 select id,
10 regexp_replace(
11 f_reverse(
12 substr(f_reverse(col), 1, 3) ||','||
13 substr(f_reverse(col), 4, 3) || chr(39) ||
14 substr(f_reverse(col), 7)
15 ), '^[^0-9]+', '') result
16 from test;
ID RESULT
---------- ----------
1 40'100,200
2 2'300,400
3 700,500
4 25,700
5 6,300
6 555
6 rows selected.
SQL>
What does it do?
lines #1 - 7 - sample data
lines #9 onward is useful code
lines #12 - 14 - splitting reversed sample data into substrings 3 characters in length
line #12 - concatenated , as this is thousands separator
line #13 - concatenaded chr(13) which is ', a millions separator
line #11 - reversing concatenated "reversed" string back
line #10 - removing possible non-numeric characters from the beginning of the result (those are separators for values that are shorter than "thousand" or "million")

FInd if the fifth position is a letter and not a number using ORACLE

How can I find if the fifth position is a letter and thus not a number using Oracle ?
My last try was using the following statement:
REGEXP_LIKE (table_column, '([abcdefghijklmnopqrstuvxyz])');
Perhaps you'd rather check whether 5th position contains a number (which means that it is not something else), i.e. do the opposite of what you're doing now.
Why? Because a "letter" isn't only ASCII; have a look at the 4th row in my example - it contains Croatian characters and these aren't between [a-z] (nor [A-Z]).
SQL> with test (col) as
2 (select 'abc_3def' from dual union all
3 select 'A435D887' from dual union all
4 select '!#$%&/()' from dual union all
5 select 'ASDĐŠŽĆČ' from dual
6 )
7 select col,
8 case when regexp_like(substr(col, 5, 1), '\d+') then 'number'
9 else 'not a number'
10 end result
11 from test;
COL RESULT
------------- ------------
abc_3def number
A435D887 not a number
!#$%&/() not a number
ASDĐŠŽĆČ not a number
SQL>
Anchor to the start of the string else you may get unexpected results. This works, but remove the caret (start of string anchor) and it returns 'TRUE'! Note it uses the case-insensitive flag of 'i'.
select 'TRUE'
from dual
where regexp_like('abcd4fg', '^.{4}[A-Z]', 'i');
Yet another way to do it:
regexp_like(table_column, '^....[[:alpha:]]')
Using the character class [[:alpha:]] will pick up all letters upper case, lower case, accented and etc. but will ignore numbers, punctuation and white space characters.
If what you care about is that the character is not a number, then use
not regexp_like(table_column, '^....[[:digit:]]')
or
not regexp_like(table_column, '^....\d')
Try:
REGEXP_LIKE (table_column, '^....[a-z]')
Or:
SUBSTR (table_column, 5, 1 ) BETWEEN 'a' AND 'z'

APEX validate alphabetic only allowed

In APEX 5.1 looking for validation script help to only allow alphabetic characters and a space or hyphen for a person's name. (i.e. no numbers or special characters other than a possible dash allowed).
I have a working validation for another field which allows alphanumeric but not special characters! Validation type is "Item does NOT contain any of the characters in Value". In the value field the following is placed... !##$%^&*()-_+=[]{};:'",<.>/?\|
I'd suggest you to use validation whose type is a function that returns Boolean and looks like this:
return regexp_like(:P1_ITEM_NAME, '^[A-Za-z -]+$');
What does it do?
^ is anchor to the beginning of the string
A-Z accepts capital letters
a-z accepts lowercase letters
space is ... well, a space
- is ... well, a hyphen
+ - repeat those characters many times
$ is anchor to the end of the string
For example:
SQL> with test (item) as
2 (select 'aBCd' from dual union -- ok
3 select 'little foot' from dual union -- ok
4 select 'reb-ecca' from dual union -- ok
5 select 'lit123foot' from dual union -- wrong
6 select 'abc$3' from dual union -- wrong
7 select 'xy.)z' from dual union -- wrong
8 select '123-234' from dual -- wrong
9 )
10 select item
11 from test
12 where regexp_like(item, '^[A-Za-z -]+$');
ITEM
-----------
aBCd
little foot
reb-ecca
SQL>

Resources