Oracle sql split string in chuncks - sql

I have a string with long multiple of 5. So the length can be: 5,10,15......
I would to split this string in chunks of 5 char to pass in the IN clausole:
String="00000111112222233333"
I would:
SELECT * FROM myTable WHERE code IN ('00000','11111','22222','33333')
Is possible to do this in Sql?

select regexp_substr(s, '.{5}', 1, lvl) chnk
from (select s, level lvl
from (select '00000111112222233333' s from dual)
connect by level <= length(s) / 5);
Use connect by to generate the desired number of rows
For each row find any 5 characters starting from the begining of the string and get Nth occurance.

Using a hierarchical query to split the string and substr to extract each chunk of data:
with data as (select '00000111112222233333' s from dual)
select substr(s, (level-1)*5+1, 5) chnk
from data
connect by level <= length(s)/5
See http://sqlfiddle.com/#!4/d41d8/37139

Related

how split string to array oracle?

How split string to array oracle?
'3/5/7'
Result:
15
You can use xmltable to generate rows from string :
More numbers are accepted.
select sum(to_number(column_value)) as SOMME from xmltable(REPLACE('3/5/7', '/', ','));
Demo here
Generate dummy rows (below: SELECT ROWNUM pos FROM dual CONNECT BY LEVEL <= 10), more than the # of elements you expect to ever have. Here I used 10, you could make it 100 or 1000 if you wanted. Label each row numerically with ROWNUM. Then use that as an operand into the SUBSTR function. This can be done with SUBSTR_REGEXP too perhaps more concisely. This will tokenize your string. Then all you have to do is aggregate the results with SUM.
SELECT SUM(item)
FROM (SELECT value,
pos,
SUBSTR(value,INSTR(value,'/',1,pos)+1,INSTR(value,'/',1,pos+1)-(INSTR(value,'/',1,pos)+1)) item
FROM (SELECT '/'||'3/5/7'||'/' value from dual),
(SELECT ROWNUM pos FROM dual CONNECT BY LEVEL <= 10))
WHERE item IS NOT NULL

Oracle SQL to shorten string in oracle

I am trying to automate API load and facing field restriction. Basically I need to shorten string if its more than 24 characters.
I am considering logic to take the first 4 characters of the word and replace space with _. A number of words in the field are dynamic.
e.g. Corporate Responsibility = copr_resp
E.g. Social Distancing Criteria = soci_dist_crit
Table_a
ColA
Corporate Responsibility
Social Distancing Criteria
Expected Result:
Select ColA, as Output from table_a;
Output
ColA Output
Corporate Responsibility copr_resp
Social Distancing Criteria soci_dist_crit
I prefer to do this using SQL. Any suggestion?
You can divide the string into row and concat again as follows:
Select t.your_col,
listagg( substr(regexp_substr(t.your_col,
'[^ ]+', 1, levels.column_value),
1, 4),
'_') within group (order by levels.column_value) as short_str
from your_table t
Cross join table(cast(multiset(select level from dual
connect by level <= length (regexp_replace(t.your_col, '[^ ]+')) + 1)
as sys.OdciNumberList)) levels
Group by t.your_col

USING SQL . extract numbers comma separated from string 'HEADER|N1000|E1001|N1002|E1003|N1004|N1005'

'HEADER|N1000|E1001|N1002|E1003|N1004|N1005'
'HEADER|N156|E1|N7|E122|N4|E5'
'HEADER|E0|E1|E2|E3|E4|E5'
'HEADER|N0|N1|N2|N3|N4|N5'
'HEADER|N125'
How to extract the numbers in comma-separated format from this stringS?
Expected result:
1000,1001,1002,1003,1004,1005
How to extract the numbers with N or E as suffix/prefix ie.
N1000
Expected result:
1000,1002,1004,1005
below regex does not return the result needed. But I want some thing like this
select REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005', '.*?(\d+)', '\1,'), ',?\.*$', '') from dual
the problem here is
when i want numbers with E OR N
select REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005', '.*?N(\d+)', '\1,'), ',?\.*$', '') from dual
select REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005', '.*?E(\d+)', '\1,'), ',?\.*$', '') from dual
they give good results for this scenerio
but when i input 'HEADER|N1000|E1001' it gives wrong answer plzzz verify and correct it
Update
Based on the changes to the question, the original answer is not valid. Instead, the solution is considerably more complex, using a hierarchical query to extract all the numbers from the string and then LISTAGG to put back together a list of numbers extracted from each string. To extract all numbers we use this query:
WITH cte AS (
SELECT DISTINCT data, level AS l, REGEXP_SUBSTR(data, '[NE]\d+', 1, level) AS num FROM test
CONNECT BY REGEXP_SUBSTR(data, '[NE]\d+', 1, level) IS NOT NULL
)
SELECT data, LISTAGG(SUBSTR(num, 2), ',') WITHIN GROUP (ORDER BY l) AS "All numbers"
FROM cte
GROUP BY data
Output (for the new sample data):
DATA All numbers
HEADER|E0|E1|E2|E3|E4|E5 0,1,2,3,4,5
HEADER|N0|N1|N2|N3|N4|N5 0,1,2,3,4,5
HEADER|N1000|E1001|N1002|E1003|N1004|N1005 1000,1001,1002,1003,1004,1005
HEADER|N125 125
HEADER|N156|E1|N7|E122|N4|E5 156,1,7,122,4,5
To select only numbers beginning with E, we modify the query to replace the [EN] in the REGEXP_SUBSTR expressions with just E i.e.
SELECT DISTINCT data, level AS l, REGEXP_SUBSTR(data, 'E\d+', 1, level) AS num FROM test
CONNECT BY REGEXP_SUBSTR(data, 'E\d+', 1, level) IS NOT NULL
Output:
DATA E-numbers
HEADER|E0|E1|E2|E3|E4|E5 0,1,2,3,4,5
HEADER|N0|N1|N2|N3|N4|N5
HEADER|N1000|E1001|N1002|E1003|N1004|N1005 1001,1003
HEADER|N125
HEADER|N156|E1|N7|E122|N4|E5 1,122,5
A similar change can be made to extract numbers commencing with N.
Demo on dbfiddle
Original Answer
One way to achieve your desired result is to replace a string of characters leading up to a number with that number and a comma, and then replace any characters from the last ,| to the end of string from the result:
SELECT REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|', '.*?(\d+)', '\1,'), ',?\|.*$', '') FROM dual
Output:
1000,1001,1002,1003,1004,1005
To only output the numbers beginning with N, we add that to the prefix string before the capture group:
SELECT REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|', '.*?N(\d+)', '\1,'), ',?\|.*$', '') FROM dual
Output:
1000,1002,1004,1005
To only output the numbers beginning with E, we add that to the prefix string before the capture group:
SELECT REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|', '.*?E(\d+)', '\1,'), ',?\|.*$', '') FROM dual
Output:
1001,1003
Demo on dbfiddle
I don't know what DBMS you are using, but here's one way to do it in Postgres:
WITH cte AS (
SELECT CAST('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|' AS VARCHAR(1000)) AS myValue
)
SELECT SUBSTRING(MyVal FROM 2)
FROM (
SELECT REGEXP_SPLIT_TO_TABLE(myValue,'\|') MyVal
FROM cte
) src
WHERE SUBSTRING(MyVal FROM 1 FOR 1) = 'N'
;
SQL Fiddle
As Far as I have understood the question , you want to extract substrings starting with N from the string, You can try following (And then you can merge the output seperated by commas if needed)
select REPLACE(value, 'N', '')
from STRING_SPLIT('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|', '|')
where value like 'N%'
OutPut :
1000
1002
1004
1005

Oracle SQL - create string by concatenating rows but does not exceed X number of characters

First I am trying to concatenate rows into string separated by comma. Second I do not want the string to be exceeded X number of character. If going to exceed then create another string from next row onward without slitting the character from each rows. I am trying to achieve this through oracle SQL.
I am looking at LISTAGG which give me the concatenated string but I have not idea how I can split by X number of characters without splitting a values from each rows, let's say my X = 15 characters. What I get using the below code is
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
select listagg(x, ',') within group(order by x)
from (select level x from dual
connect by level <= 20
)
;
My expected output will be,
row 1: 1,2,3,4,5,6,7,8 (15 characters)
row 2: 9,10,11,12,13 (13 characters because that going to exceed 15 if I add value from next row)
row 3: 14,15,16,17,18 (14 characters)
row 4: 19,20 (5 characters)
I am still not sure this can be achieved, any suggestion or hint will be most appreciated.
I tried the following query and achieved the desired result.
SELECT
LISTAGG(X, ',') WITHIN GROUP(
ORDER BY
X
) as result
FROM
(
SELECT
X,
SUM(LENGTH(X)) OVER(
ORDER BY
X
) LENGTH_X,
COUNT(1) OVER(
ORDER BY
X
) - 1 AS COMMAS
FROM
(
SELECT
LEVEL X
FROM
DUAL
CONNECT BY
LEVEL <= 20
)
)
GROUP BY
CEIL((LENGTH_X + COMMAS) / 15);
Output:
db<>fiddle demo
Cheers!!

Oracle regexp_substr - Find and extract all occurances in a column

I'm working with an Oracle DB and I'm trying to find and extract ALL occurrences in a string matching a specific pattern...
It's supposed to be 3 letters, 3 numbers and then maybe a letter or not
I tried this:
SELECT REGEXP_SUBSTR(my_column, '[A-Za-z]{3}(\d)(\d)(\d)') AS values
FROM my_table
but it only returns the first occurrence.
Using
REGEXP_SUBSTR(my_column, '[A-Za-z]{3}(\d)(\d)(\d)', 0, 0, 'i')
doesn't work either
Does anybody have any ideas?
Edit:
I'm trying to extract it from PLSQL files. So its pretty much like SQL queries like
select *
from abc123
where some_value = 'some_value'
Try this query to break ABC123CDE456FGHI789 squence
with mine as (select 'ABC123CDE456FGH789' hello from dual)
select regexp_substr(hello, '[A-Za-z]{3}(\d){3}', 1, level) STR from mine
connect by regexp_substr(hello, '[A-Za-z]{3}(\d){3}', 1, level) is not null
Output
ABC123
CDE456
GHI789
For get specific postion then you want to use
select regexp_substr('ABC123CDE456FGH789', '[A-Za-z]{3}(\d){3}', 1, i) STR from dual
change i value as per position like
select regexp_substr('ABC123CDE456FGH789', '[A-Za-z]{3}(\d){3}', 1, 1) STR from dual
Output :
ABC123
Try to get number in 1.2.3 (suppose it is a domain of a country)
SELECT str,level,REGEXP_SUBSTR(str, '[0-9]', 1, LEVEL) AS substr
FROM (
SELECT country_domain str from country where regexp_like(country_domain, '[0-9]')
)
CONNECT BY LEVEL <= REGEXP_count(str, '[0-9]');
Output
STR LEVEL SUBSTR
1.2.3 1 1
1.2.3 2 2
1.2.3 3 3