How to replace a new line character with row number within a string based on id following is the sample from one row from a table ,table has so many rows and each row should starts with 1.and so on.
sample data
I
am
Awesome
desired out put
1.I
2.am
3.Awesome
I tried to replace newline with rownumber but no success
select concat(1.,replace(field,char(10),cast(1+row_number()over(order by field) as varchar),'.') as desired_Formula from tbl
any help or suggestions are welcomed , It should be ideal if it's done without using cte.
One option would be to create an array based on the newline character, then UNNEST .. WITH ORDINALITY, so that you have a row number, and from there turn it again into a single row with string_agg:
SELECT string_agg(id || '.' || word,E'\n')
FROM tbl
CROSS JOIN LATERAL
UNNEST(string_to_array(sample,E'\n')) WITH ORDINALITY j (word,id)
GROUP BY sample;
string_agg
------------
1.I +
2.am +
3.Awesome
(1 Zeile)
If you want to split the items in many rows, just get rid of the string_agg and the GROUP BY clause:
SELECT id || '.' || word
FROM tbl
CROSS JOIN LATERAL
UNNEST(string_to_array(sample,E'\n')) WITH ORDINALITY j (word,id);
?column?
-----------
1.I
2.am
3.Awesome
(3 Zeilen)
Demo: db<>fiddle
The following code is working fine when the column 'generated_key ' return one value
WHERE code IN ( SELECT generated_key FROM List_agg )
CODE
generated_key
EU00100ST10000016
EU00100ST10000016
But when the column generated_key containt more than a values, it return 0 rows
CODE
generated_key
EU00100ST10000016
EU00100ST10000016, EU00100ST10000017
If you need to compare to a list, use delimited comparisons
WHERE EXISTS (SELECT 1
FROM list_agg
WHERE ',' || generated_key || ',' LIKE '%,' || code ',%'
)
The "list_agg" name suggests that you are aggregating values from another query. If so, you might be able to use use in with no aggregation. But your question doesn't have enough details to know if that is really the case.
I am looking for some help in separating scientific names in my data. I want to take only the genus names and group them, but they are both connected in the same column. I saw the SQL Sever had a CHARINDEX command, but PostgreSQL does not. Does there need to be a function created for this? If so, how would it look?
I want to change 'Mallotus philippensis' to just 'Mallotus' or to just 'philippensis'
I am currently using Postgres 11, 12.
Use SPLIT_PART:
WITH yourTable AS (
SELECT 'Mallotus philippensis'::text AS genus
)
SELECT
SPLIT_PART(genus, ' ', 1) AS genus,
SPLIT_PART(genus, ' ', 2) AS species
FROM yourTable;
Demo
Probably string_to_array will be slightly more efficient than split_part here because string splitting will be done only once for each row.
SELECT
val_arr[1] AS genus,
val_arr[2] AS species
FROM (
SELECT string_to_array(val, ' ') as val_arr
FROM (
VALUES
('aaa bbb'),
('cc dddd'),
('e fffff')
) t (val)
) tt;
I want remove specific value from comma separated sting using oracle.
Sample Input -
col
1,2,3,4,5
Suppose i want to remove 3 from the string.
Sample Output -
col
1,2,4,5
Please suggest how i can do this using oracle query.
Thanks.
Here is a solution that uses only standard string functions (rather than regular expressions) - which should result in faster execution in most cases; it removes 3 only when it is the first character followed by comma, the last character preceded by comma, or preceded and followed by comma, and it removes the comma that precedes it in the middle case and it removes the comma that follows it in the first and third case.
It is able to remove two 3's in a row (which some of the other solutions offered are not able to do) while leaving in place consecutive commas (which presumably stand in for NULL) and do not disturb numbers like 38 or 123.
The strategy is to first double up every comma (replace , with ,,) and append and prepend a comma (to the beginning and the end of the string). Then remove every occurrence of ,3,. From what is left, replace every ,, back with a single , and finally remove the leading and trailing ,.
with
test_data ( str ) as (
select '1,2,3,4,5' from dual union all
select '1,2,3,3,4,4,5' from dual union all
select '12,34,5' from dual union all
select '1,,,3,3,3,4' from dual
)
select str,
trim(both ',' from
replace( replace(',' || replace(str, ',', ',,') || ',', ',3,'), ',,', ',')
) as new_str
from test_data
;
STR NEW_STR
------------- ----------
1,2,3,4,5 1,2,4,5
1,2,3,3,4,4,5 1,2,4,4,5
12,34,5 12,34,5
1,,,3,3,3,4 1,,,4
4 rows selected.
Note As pointed out by MT0 (see Comments below), this will trim too much if the original string begins or ends with commas. To cover that case, instead of wrapping everything within trim(both ',' from ...) I should wrap the rest within a subquery, and use something like substr(new_str, 2, length(new_str) - 2) in the outer query.
Here is one method:
select trim(both ',' from replace(',' || '1,2,3,4,5' || ',', ',' || '3' || ',', ','))
That said, storing comma-delimited strings is a really, really bad idea. There is almost no reason to do such a thing. Oracle supports JSON, XML, and nested tables -- all of which are better alternatives.
The need to remove an element suggests a poor data design.
You can convert the list rows using an XMLTABLE, filter to remove the unwanted rows and then re-aggregate them:
SELECT LISTAGG( x.value.getStringVal(), ',' ) WITHIN GROUP ( ORDER BY idx )
FROM XMLTABLE(
( '1,2,3,4,5' )
COLUMNS value XMLTYPE PATH '.',
idx FOR ORDINALITY
) x
WHERE x.value.getStringVal() != 3;
For a simple filter this is probably not worth it and you should use something like (based on #mathguy's solution):
SELECT SUBSTR( new_list, 2, LENGTH( new_list ) - 2 ) AS new_list
FROM (
SELECT REPLACE(
REPLACE(
',' || REPLACE( :list, ',', ',,' ) || ',',
',' || :value_to_replace || ','
),
',,',
','
) AS new_list
FROM DUAL
)
However, if the filtering is more complicated then it might be worth converting the list to rows, filtering and re-aggregating.
I do not knwo how to do this in Oracle, but with SQL-Server I'd use a trick:
convert the list to XML by replacing the comma with tags
use XQuery to filter the data
reconcatenate
This is SQL Server syntax but might point you the direction:
declare #s varchar(100)='1,2,2,3,3,4';
declare #exclude int=3;
WITH Casted AS
(
SELECT CAST('<x>' + REPLACE(#s,',','</x><x>') + '</x>' AS XML) AS TheXml
)
SELECT x.value('.','int')
FROM Casted
CROSS APPLY TheXml.nodes('/x[text()!=sql:variable("#exclude")]') AS A(x)
UPDATE
I just found this answer which seems to show pretty well how to start...
I agree with Gordon regarding the fact that storing comma delimited data in a column is a really bad idea.
I just preceed the csv with a ',', then use the replace function followed by a left trim function to clean-up the preceeding ','.
SCOTT#tst>VAR b_number varchar2(5);
SCOTT#tst>EXEC :b_number:= '3';
PL/SQL procedure successfully completed.
SCOTT#tst>WITH srce AS (
2 SELECT
3 ',' || '3,1,2,3,3,4,5,3' col
4 FROM
5 dual
6 ) SELECT
7 ltrim(replace(col,',' ||:b_number),',') col
8 FROM
9 srce;
COL
1,2,4,5
I'm trying to turn object_type,ABC,00,DEF,XY string into ABC-00-DEF-XY-
Here's what I've got, I'm wondering if there is a more efficient way?
CONCAT(
REPLACE(
SUBSTR(a.object_name,
INSTR(a.object_name, ',',1,1)+1,
INSTR(a.object_name, ',',1,2)+1
),',','-'
),'-'
)
Clarification: I need to strip off everything up to and including the first comma, replace all remaining commas with dashes, and then add a dash onto the end.
Try this
replace(substr(a.object_name,instr(a.object_name,',',1,1) + 1),',','-') ||'-'
Rexexp_replace() regular expression function can come in handy in this situation as well:
select ltrim(
regexp_replace( col
, '([^,]+)|,([^,]+)', '\2-'
)
, '-'
) as res
from t1
Result:
RES
--------------
ABC-00-DEF-XY-
SQLFiddle Demo
I suggest using the following code:
REPLACE(SUBSTRING(a.object_name,13,LEN(#object_name)-11),',','-') + '-'