Please can anybody help me out please. Have been trying for days to get a regexp_replace to remove commas between quotes irrespective of the commas position.
Example
cold, gold, "Block 12C, Jones Avenue, Broad Street, London", car
Expected Answer
cold, gold, "Block 12C Jones Avenue Broad Street London", car
thanks in advance
You could extract the contents within double quotes(REGEXP_SUBSTR), replace the commas, and stuff it back to the old string using replace.
select REPLACE (whole_str,quoted_str,REPLACE (quoted_str,',')) FROM
(
select
whole_str,
REGEXP_SUBSTR( whole_str, '^[^"]*("[^"]+")',1,1,NULL,1) quoted_str
FROM yourtable
);
DEMO
Note that this could also be done using INSTR,SUBSTR which could be more efficient, but hard to read.
You can use regexp_replace to get the desired output :
with t( id , val ) as(
select 1,'cold, gold, "Block 12C, Jones Avenue, Broad Street, London", car' from dual union
select 2,'"Block 12C, Jones Avenue, Broad Street, London", car, cold, gold' from dual )
select id, val value
from t
model dimension by( id ) measures( val )
rules iterate(100)( val[any] = regexp_replace(val[cv()],',(([^"]*"){2})*([^"]*"[^"]*)$',' \1\3') );
d E m O
I doubt that there is a single regular expression function that will achieve the desired result. The "obvious" line of attack is to chop the input string into pieces and delete commas from each double-quoted substring as needed. (Unless each string has at most ONE double-quoted substring, in which case the problem has easier answers - but judging from the sample input string, it is possible that the same needs to be done for input strings with an arbitrary number of double-quoted substrings.)
Here is a solution using a recursive WITH clause - so it requires Oracle 11.2 or higher. (For earlier versions, a solution with a CONNECT BY hierarchical query can be used instead.) I wrote it with regular expressions, as requested; if speed becomes an issue, it can be re-written with standard INSTR, SUBSTR and REPLACE functions.
In the first factored subquery (subquery in the WITH clause) I created a few more inputs, to test whether the solution returns the correct result in different situations.
with
inputs ( str ) as (
select 'cold, gold, "Block 12C, Jones Ave., London", car' from dual union all
select '"One, two, three","Four, five six,",' from dual union all
select 'No, double-quotes, in this, string' from dual union all
select 'No commas in "double quotes" here' from dual
),
r ( str, init, quoted, fin ) as (
select str, null, null, str
from inputs
union all
select str,
init || replace(quoted, ',') || regexp_substr(fin, '[^"]*'),
regexp_substr(fin, '"[^"]*"'),
regexp_substr(fin, '([^"]*"){2}(.*)', 1, 1, null, 2)
from r
where quoted is not null or fin is not null
)
select str, init as new_str
from r
where quoted is null and fin is null
;
STR NEW_STR
--------------------------------------------- -------------------------------------------
No, double-quotes, in this, string No, double-quotes, in this, string
cold, gold, "Block 12C, Jay Ave, London", car cold, gold, "Block 12C Jay Ave London", car
No commas in "double quotes" here No commas in "double quotes" here
"One, two, three","Four, five six,", "One two three","Four five six",
Related
I'm trying to split the string "SMITH\nALLEN\WARD\nJONES" in Oracle 10g by newline "\n" using a single SELECT query. Please help me to find the exact Regular Expression for this.
Expected Output:
1 SMITH
2 ALLEN\WARD
3 JONES
I have tried the expression "[^\n]+", but I got the following result which considered "\" as well. I want the expression to consider only "\n".
Query:
SELECT REGEXP_SUBSTR ('SMITH\nALLEN\WARD\nJONES',
'[^\n]+',
1,
LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR ('SMITH\nALLEN\WARD\nJONES',
'[^\n]+',
1,
LEVEL) IS NOT NULL;
Result:
1 SMITH
2 ALLEN
3 WARD
4 JONES
Within the [] the characters are matched individually, and \n isn't seen a special character or even a run of characters anyway - it matches either of those characters individually; so even changing to [^\\n] wouldn't help.
You can use this form, which also returns empty elements:
select regexp_substr('SMITH\nALLEN\WARD\nJONES', '(.*?)(\\n|$)', 1, level, 'm', 1)
from dual
connect by level <= regexp_count('SMITH\nALLEN\WARD\nJONES', '\\n') + 1;
REGEXP_SUBSTR('SMITH\NAL
------------------------
SMITH
ALLEN\WARD
JONES
I'm having this problem we have this database witch IDS are stored in varchar2 type this ids contains Letters.
Is there any solution to convert a string to a number no matter what the value if this string.
for example there is : SELCT ASCII('t') FROM DUAL; result : 116.
but ASCII accept only one CHAR Hope you get the idea. sorry for my english
use oracle translate method to replace A-Z or a-z characters with numbers.
then use to_number to get number from it.
select translate('A1B2C3', 'ABC', '456') from dual; --result '415263'
select to_number(translate('A1B2C3', 'ABC', '456')) from dual; --result 415263
translate function documentation
The Oracle/PLSQL TRANSLATE function replaces a sequence of characters in a string with another set of characters. However, it replaces a single character at a time.
For example, it will replace the 1st character in the string_to_replace with the 1st character in the replacement_string. Then it will replace the 2nd character in the string_to_replace with the 2nd character in the replacement_string, and so on.
EDIT: After discussing further with the OP, it turns out he needed a function (in the mathematical sense) from short strings to integers. Such a function is ORA_HASH. The OP decided that ORA_HASH is likely what is needed for his project.
https://docs.oracle.com/cd/B28359_01/server.111/b28286/functions112.htm#SQLRF06313
The solution below is kept for historical perspective.
You could use the analytic function DENSE_RANK to assign numbers to strings.
For example:
with
employees ( id, first_name, last_name ) as (
select 'ABC', 'Jane', 'Smith' from dual union all
select 'ABD', 'Jane', 'Dryer' from dual union all
select 'XYZ', 'Mike', 'Lopez' from dual
)
-- End of simulated inputs (for testing purposes only).
-- Solution (SQL query) begins below this line.
select id, dense_rank() over (order by id) as num_id, first_name, last_name
from employees
;
ID NUM_ID FIRST_NAME LAST_NAME
--- ------ ---------- ---------
ABC 1 Jane Smith
ABD 2 Jane Dryer
XYZ 3 Mike Lopez
I've got a table with names in it, which looks like this:
Emp_ID Emp_Name
0001 Jack Skelly
0002 Susan Ryan
I need to produce something that looks like this:
Emp_ID Emp_F_Name Emp_L_Name
0001 Jack Skelly
0002 Susan Ryan
I've come up with this to split the name:
SubStr(d.Name, 0, InStr(d.Name, ' ')-1) as FName,
SubStr(d.Name, InStr(d.Name, ' ')+1) as LName
I've seen people suggest INSTR, I've seen people suggest regexp_instr and I've seen them suggest regexp_substr. I'm still new to Oracle and I don't really understand either, or which (if either) of them is more efficient for the split I need to do. Can someone tell me the best way to go about splitting this field? Is the method I've used the best/most efficient for what I want to do?
substr and instr are almost always faster/more efficient than regular expression functions.
INSTR is used to find the position of the space in the input string. SUBSTR is used to extract a substring from the input string. Search (google) the Oracle documentation for these functions - you will find detailed explanations and examples.
The bigger issue you will have with your problem is the business requirement - what do you do with names like "John Clayton Stuart", "Ali Abu Ahmad", or single-word like "Belphegor"?
The query below shows how easily you can solve the problem if all the names have the format "Firstname Lastname".
with
input_table ( emp_id, emp_name ) as (
select '0001', 'Jack Skelly' from dual union all
select '0002', 'Susan Ryan' from dual
)
-- End of simulated input data (not part of the solution).
-- SQL query begins BELOW THIS LINE.
select emp_id, emp_name,
substr(emp_name, 1, instr(emp_name, ' ') - 1) as first_name,
substr(emp_name, instr(emp_name, ' ') + 1) as last_name
from input_table
;
EMP_ID EMP_NAME FIRST_NAME LAST_NAME
---- ----------- ----------- -----------
0001 Jack Skelly Jack Skelly
0002 Susan Ryan Susan Ryan
how to display second or third letter in each word of sentence as CAPITAL letter in Oracle.
Testdata:
hyderabad
Output:
hYderabad or hyDerabad
To make 2nd character to upper case
select SUBSTR(test_data,1,1)||INITCAP(SUBSTR(test_data,2)) from test_table;
To make the 3rd character to upper case, increment the last argument of both SUBSTR with 1.
Example
select SUBSTR(test_data,1,2)||INITCAP(SUBSTR(test_data,3)) from test_table;
Use this for 2nd digit as upper case.
WITH TBL(TESTDATA) AS
( SELECT 'hyderabad' FROM DUAL UNION
SELECT 'pune' FROM DUAL UNION
SELECT '223jjjj22' FROM DUAL
)
SELECT substr(testdata,1,1)||upper(substr(testdata,2,1))
||substr(testdata,3,length(testdata)-2)
as output
FROM TBL
Output
223jjjj22
hYderabad
pUne
Here I fetched first character,upper case of second character and rest of characters separately. Then I concatenated them.
You can use similar approach for 3rd character if you want.
i'm sorry for this probably a stupid question, but i have to make a couple of queries for a test, but i do not have access to a decent computer with the right software so basically i can only use pen and paper and have access to internet.
Assignment > Create a function that changes all the English consonant letters into uppercase and all the English
vowels into lowercase. (Hints: c CHAR; c > 'a', INSTR). Example:
funnycase('christmas time') => 'CHRiSTMaS TiMe'
I was thinking more like a programmer and thought that maybe there is a way to do it like:
CREATE FUNCTION f1 (in_word IN VARCHAR(20)) RETURN VARCHAR (20)
IS answer VARCHAR(20);
BEGIN;
DECLARE CHAR c;
So here is where i fail and i need help:
FOR char IN in_word .... if char NOT IN ("a","e", "i", "o", "u") THEN UPPERCASE char
Else pass?
Another thing is i do not know how to add it to answer
Answer add char?
Return answer;
End;
I am totally unclear how instr works and I can't understand how to use it without help of a computer.
I am programming with pen and paper.
Also I wrote another query:
Study how LISTAGG function works. Write a query that lists all the departments ordered by
department name. Show
· department name,
· location,
· comma-separated list of people in that department ordered by name,
· average salary compared to company average in %
Only knowing data from there https://courses.cs.ut.ee/MTAT.03.288/2013_fall/uploads/Main/p06_data.txt
SELECT dname, loc, LISTAGG(ename, "; ") WITHIN GROUP (ORDER BY ename),
TRUNC( ( (SUM(sal) OVER () ) / ( SUM(sal) OVER (PARTITION BY dname) ) , 2 ) AS AvgSal
FROM (SELECT DISTINCT t1.dname, t1.location, t2.ename, t2.sal FROM Dept t1, EMP t2
WHERE t1.deptno = t2.deptno ) ORDER BY dname;