Split multiple values in a cell to multiple rows - Oracle SQL - sql

I have a table:
table1
values
------------
x=new letter
------------
a=old letter
ba=older letter
xq=newer letter
------------
xf=new apple
xt=new orange
x3=new fruit
xtt=new seed
I have to separate the values in each cell to multiple rows.
The following is the output:
table2
code description
x new letter
a old letter
ba older letter
xq newer letter
xf new apple
xt new orange
x3 new fruit
xtt new seed
How can this be achieved?

I would use regexp_replace() or regexp_substr():
select regexp_substr(str, '^[^=]+') as code,
regexp_substr(str, '[^=]+$') as value
Here is a db<>fiddle.
Note that this does not use values for the column name. That is a very bad choice for a column name because it is a SQL keyword.

try like below
SELECT NVL(SUBSTR('a=old letter', 0, INSTR('a=old letter', '=')-1), 'a=old letter')
AS col1, NVL(SUBSTR('a=old letter', INSTR('a=old letter', '=')+1), 'a=old letter')
FROM DUAL
so in you case
SELECT NVL(SUBSTR(values, 0, INSTR(values, '=')-1), values)
AS col1, NVL(SUBSTR(values, INSTR(values, '=')+1), values)
FROM table1

Related

How to obtain last string after right-most space

Dataset looks like this
Column A
Column B
Apple
Apple Banana
Corn
Corn Chips
I would want "Banana" returned from the first row and "Chips" returned from the second row.
I've done (instr (Column B, ' ', -2)
This gives me the location of the space
I know I need to use a substr in conjunction with this, but for substr I need to specify the length of characters I want to retrieve right? How do I overcome the problem where the length of characters after the last space is different each time?
I know I need to use a substr in conjunction with this, but for substr I need to specify the length of characters I want to retrieve right?
No, if you do not specify the number of characters then the SUBSTR function will return the rest of the string.
So you can use:
SELECT SUBSTR(column_b, INSTR(column_b, ' ', -1) + 1) AS last_word
FROM table_name;
To get the substring after the last space.
Which, for the sample data:
CREATE TABLE table_name (Column_A, Column_B) AS
SELECT 'Apple', 'Apple Banana' FROM DUAL UNION ALL
SELECT 'Corn', 'Corn Chips' FROM DUAL;
Outputs:
LAST_WORD
Banana
Chips
fiddle
A simple option is to use regular expression, by fetching one or more occurrences + of a word \w which is anchored to the end $ of the string.
Sample data:
SQL> with test (cola, colb) as
2 (select 'apple', 'apple banana' from dual union all
3 select 'corn' , 'corn chips' from dual
4 )
Query begins here:
5 select cola, colb,
6 --
7 regexp_substr(colb, '\w+$') last_word
8 from test;
COLA COLB LAST_WORD
----- ------------ ------------
apple apple banana banana
corn corn chips chips
SQL>

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

Where x character equal value

How can I select records where in the column Value the 5th character is letter A?
For example the following records:
ID Value
-------------------------
1 1234A5636A6363
2 1234A4343B6363
3 1234B5353A6363
if I run
select * from table
where Value like '%A%'
this will return all records
but all I want is the first 2 where the 5th character is A, regardless if there are more A characters in the text or not
select *
from your_table
where substring(Value, 5, 1) = 'A'
The LIKE operator, in addition to %, which matches any number of any character, can use _, which matches any one single character. You may try:
SELECT *
FROM yourTable
WHERE Value LIKE '____A%'; -- 4 underscores here
use like below by using _(underscore)
LIKE '____A%'
SQL Server
select *
from YourTableName
where CHARINDEX('A', ColumnName) = 5
Note:- This finds where string 'A' starts at position 5
AND specify Your ColumnName

Find and Replace a strings in oracle

I have a string which contains data as follows:
'ID,MASTER_ID,DATA_SOURCE_ID,DATA_SOURCE_NAME,CHILD_COUNT,CHILD_COUNT_TEXT,PARENT_OR_CHILD,RECORD_TYPE,FULL_NAME_LNF,FULL_NAME_FNF,FIRST_NAME,LAST_NAME,PREFIX,SUFFIX,MIDDLE,TITLE,NAME_OF_ORGANIZATION,NAME_OF_BUSINESS,TYPE_OF_ENTITY,ADDRESS,CITY,STATE,PROVINCE,POSTAL_CODE,COUNTRY,POSTAL_ADDRESS_TYPE,PHONE_AREA_CODE,PHONE_NUMBER,PHONE_COUNTRY_CODE,PHONE,PHONE_TYPE,EMAIL_ADDRESS,URL,HCP_SPECIALTY,HCP_TYPE,HCP_SUBTYPE,RECIPIENT_STATUS,COVERED_RECIPIENT_FLAG,RELATIONSHIP_TO_CR,LAST_MODIFIED_BY,LAST_MODIFIED_DATE,PRIMARY_LICENSE_STATE_AR,PRIMARY_LICENSE_NUM_AR,DEA_REG_NUM_AR,NPI_NUM_AR,UPIN_AR,TAX_PAYER_ID_AR,PRIMARY_LICENSE_STATE_CR,PRIMARY_LICENSE_NUM_CR,DEA_REG_NUM_CR,NPI_NUM_CR,UPIN_CR,DEA_NUMBER,NPI,UPIN,TIN,TAX_PAYER_ID_CR,ATTRIBUTE13,ATTRIBUTE14,ATTRIBUTE15,ATTRIBUTE16,ATTRIBUTE17,ATTRIBUTE18,ATTRIBUTE19,ATTRIBUTE20,ATTRIBUTE21,ATTRIBUTE22,ATTRIBUTE23,ATTRIBUTE24,ATTRIBUTE25,ATTRIBUTE26,ATTRIBUTE27,ATTRIBUTE28,ATTRIBUTE29,ATTRIBUTE30,SOURCE_REGION_CODE,SOURCE_SYSTEM_CODE,REC_INVALID_FLAG,REVISION_FLAG,IS_ACTIVE,PROCESS_STATE,RECIPIENT_CATEGORY01,RECIPIENT_CATEGORY02,RECIPIENT_CATEGORY03,RECIPIENT_CATEGORY04,RECIPIENT_CATEGORY05,RECIPIENT_CATEGORY06,RECIPIENT_CATEGORY07,RECIPIENT_CATEGORY08,RECIPIENT_CATEGORY09,RECIPIENT_CATEGORY10,RECIPIENT_CATEGORY11,RECIPIENT_CATEGORY12,RECIPIENT_CATEGORY13,RECIPIENT_CATEGORY14,RECIPIENT_CATEGORY15,RECIPIENT_CATEGORY16,RECIPIENT_CATEGORY17,RECIPIENT_CATEGORY18,RECIPIENT_CATEGORY19,RECIPIENT_CATEGORY20,RECIPIENT_CATEGORY21,RECIPIENT_CATEGORY22,RECIPIENT_CATEGORY23,RECIPIENT_CATEGORY24,RECIPIENT_CATEGORY25,RECIPIENT_CATEGORY26,RECIPIENT_CATEGORY27,RECIPIENT_CATEGORY28,RECIPIENT_CATEGORY29,RECIPIENT_CATEGORY30,IS_PICKABLE,IS_GOLDEN,PRIMARY_LICENSE_NUM,PRIMARY_LICENSE_EFFECTIVE,PRIMARY_LICENSE_EXPIRES,TERTIARY_LICENSE_EFFECTIVE,TERTIARY_LICENSE_EXPIRES,SECONDARY_LICENSE_EFFECTIVE,SECONDARY_LICENSE_EXPIRES,SECONDARY_LICENSE_NUM,TERTIARY_LICENSE_NUM,ADDRESS2,PHONE_AREA_CODE2,PHONE_NUMBER2,PHONE_COUNTRY_CODE2,PHONE_TYPE2,TERRITORY,PRIMARY_AFFILIATION,PRIMARY_AFFILIATION_STATE,REQUEST_WF_STATE,IS_EDIT_LOCKED,SOURCE_SYSTEM_RECIPIENT_ID,CREATED_BY,CREATION_DATE,APPROVER_COMMENTS,SECONDARY_LICENSE_STATE,PRIMARY_LICENSE_STATE,NPI_DATA,STATE_DATA,DEA_DATA,RPPS,FINESS,SIREN_NUMBER,DPC'
Can anybody tell me how to find only the following values
DATA_SOURCE_ID,
LAST_MODIFIED_BY,
LAST_MODIFIED_DATE,
ATTRIBUTE13,
ATTRIBUTE14,
ATTRIBUTE15,
ATTRIBUTE16,
ATTRIBUTE17,
ATTRIBUTE18,
ATTRIBUTE19,
ATTRIBUTE20,
ATTRIBUTE21,
ATTRIBUTE22,
ATTRIBUTE23,
ATTRIBUTE24,
ATTRIBUTE25,
ATTRIBUTE26,
ATTRIBUTE27,
ATTRIBUTE28,
ATTRIBUTE29,
ATTRIBUTE30,
And then replace them with following strings
'L.DATA_SOURCE_ID,L.LAST_MODIFIED_BY,L.LAST_MODIFIED_DATE,L.ATTRIBUTE13,L.ATTRIBUTE14,L.ATTRIBUTE15,L.ATTRIBUTE16,L.ATTRIBUTE17,L.ATTRIBUTE18,L.ATTRIBUTE19,L.ATTRIBUTE20,L.ATTRIBUTE21,L.ATTRIBUTE22,L.ATTRIBUTE23,L.ATTRIBUTE24,L.ATTRIBUTE25,L.ATTRIBUTE26,L.ATTRIBUTE27,L.ATTRIBUTE28,L.ATTRIBUTE29,L.ATTRIBUTE30,'
You are looking for this. It gives you your desired result
SELECT mycol, CONCAT('L.', mycol) AS newCol
FROM(SELECT * FROM test WHERE mycol REGEXP
'DATA_SOURCE_ID|LAST_MODIFIED_BY|LAST_MODIFIED_DATE|ATTRIBUTE[0-9]+')
as temp
EXPLANATION
SELECT * FROM test WHERE mycol REGEXP
'DATA_SOURCE_ID|LAST_MODIFIED_BY|LAST_MODIFIED_DATE|ATTRIBUTE[0-9]+')
This finds all rows that either have DATA_SOURCE_ID or LAST_MODIFIED_BY or LAST_MODIFIED_DATE or ATTRIBUTE followed by any number
SELECT mycol, CONCAT('L.', mycol) AS newCol
This adds L. to all the rows that has been found by the subquery.
OUTPUT
L.DATA_SOURCE_ID,
L.LAST_MODIFIED_BY,
L.LAST_MODIFIED_DATE,
L.ATTRIBUTE13,
L.ATTRIBUTE14,
L.ATTRIBUTE15,
L.ATTRIBUTE16,
L.ATTRIBUTE17,
L.ATTRIBUTE18,
L.ATTRIBUTE19,
L.ATTRIBUTE20,
L.ATTRIBUTE21,
L.ATTRIBUTE22,
L.ATTRIBUTE23,
L.ATTRIBUTE24,
L.ATTRIBUTE25,
L.ATTRIBUTE26,
L.ATTRIBUTE27,
L.ATTRIBUTE28,
L.ATTRIBUTE29,
L.ATTRIBUTE30
Hope this helps
You can try like this:
replace( replace(myString, 'DATA_SOURCE_ID', 'yourReplaceValue1'), 'LAST_MODIFIED_BY', yourReplaceValu2).....
This ..... is for you to make the similar replace for the rest of your replacing strings :)
Use nested REPLACE:
SQL> WITH data AS
2 ( SELECT 'a,b,c' str FROM dual
3 )
4 SELECT str,
5 REPLACE(REPLACE(REPLACE(str, 'a', 'x'), 'y'), 'z') new_str
6 FROM data;
STR NEW_S
----- -----
a,b,c x,b,c

pgsql parse string to get a string after certain position

I have a table column that has data like
NA_PTR_51000_LAT_CO-BOGOTA_S_A
NA_PTR_51000_LAT_COL_M_A
NA_PTR_51000_LAT_COL_S_A
NA_PTR_51000_LAT_COL_S_B
NA_PTR_51000_LAT_MX-MC_L_A
NA_PTR_51000_LAT_MX-MTY_M_A
I want to parse each column value so that I get the values in column_B. Thank you.
COLUMN_A COLUMN_B
NA_PTR_51000_LAT_CO-BOGOTA_S_A CO-BOGOTA
NA_PTR_51000_LAT_COL_M_A COL
NA_PTR_51000_LAT_COL_S_A COL
NA_PTR_51000_LAT_COL_S_B COL
NA_PTR_51000_LAT_MX-MC_L_A MX-MC
NA_PTR_51000_LAT_MX-MTY_M_A MX-MTY
I'm not sure of the Postgresql and I can't get SQL fiddle to accept the schema build...
substring and length may vary...
Select Column_A, substr(columN_A,18,length(columN_A)-17-4) from tableName
Ok how about this then:
http://sqlfiddle.com/#!15/ad0dd/56/0
Select column_A, b
from (
Select Column_A, b, row_number() OVER (ORDER BY column_A) AS k
FROM (
SELECT Column_A
, regexp_split_to_table(Column_A, '_') b
FROM test
) I
) X
Where k%7=5
Inside out:
Inner most select simply splits the data into multiple rows on _
middle select adds a row number so that we can use the use the mod operator to find all occurances of a 5th remainder.
This ASSUMES that the section of data you're after is always the 5th segment AND that there are always 7 segments...
Use regexp_matches() with a search pattern like 'NA_PTR_51000_LAT_(.+)_'
This should return everything after NA_PTR_51000_LAT_ before the next underscore, which would match the pattern you are looking for.