Postgres Query to replace the last occurence of input data - sql

Input:
field
ABC_PKG_T
ABC_T_PKG
ABC_PKG_T2
abc_base_t
Output:
field
ABC_PKG
ABC_T_PKG
ABC_PKG_T2
abc_base
I have used the following logic:
REGEXP_REPLACE(TRIM(field), '(.*)\_T|_t', '\1' )
and it's working fine to fetch most of the output value except for the third output value I am getting "ABC_PKG2".
Can you please suggest any other logic so that I will get the result as ABC_PKG_T2 correctly?

You need to anchor the expression at the end of the string using $:
regexp_replace(the_column, '_t\s*$', '', 'i')
The \s* will also remove any trailing white space that follow the _t and the 'i' makes this case insensitive so it will remove _T as well as _t

Related

Inserting special characters inside a string without replacing any character

Suppose I have a varchar variable.Can I insert different symbols after evry 2 character of the string untill end of the string .i.e untill length (string).
For example:
Input: '12345678'
And we don't know what is input and length of input and the output we want is :
Output: '12_34&56#78' (special character can be anything )
Please let me know if it possible doing dynamically using loop or something.
This can be done using a simple REGEXP_REPLACE.
The first argument will be your original string.
The second argument will be your regex pattern you want to put a a character after. In this case it is . (any character) occurring 2 times. It is surrounded by parentheses which will be needed for the next argument to specify a capture group.
The third argument is using \1 to specify the first capture group, then you can put anything you'd like to appear after the capture group. In the example below I used a !.
SELECT REGEXP_REPLACE ('12345678', '(.{2})', '\1!') as str FROM DUAL;
STR
_______________
12!34!56!78!
If you do not want the character at the end of your string, you can TRIM it from the right side or SUBSTR if the special character may appear at the end of the original string.
You can use an hierarchical query during the split and padding a special character through use of DBMS_RANDOM.VALUE in order to produce some special characters except for the last piece, and then LISTAGG() function to combine the pieces back again such as
SELECT id,LISTAGG( SUBSTR(col,1+(level-1)*2,2)||
CASE WHEN level < CEIL(LENGTH(col)/2)
THEN
CHR(TRUNC(DBMS_RANDOM.VALUE(33,48)))
END)
WITHIN GROUP (ORDER BY level)
AS result
FROM t
GROUP BY id
CONNECT BY level <= CEIL(LENGTH(col)/2)
AND PRIOR SYS_GUID() IS NOT NULL
AND PRIOR ID = ID
Demo

How can I remove characters in a string after a specific special character (~) in snowflake sql?

I am using Snowflake SQL. I would like to remove characters from a string after a special character ~. How can I do that?
here is the whole scenario. Let me explain. I do have a string like 'CK#123456~fndkjfgdjkg'. Now, i want only the number after #.And not anything after ~. This is number length varies for that field value. It might be 1 or 5 or 3. And i want to add the condition in where class where this number is equal to check_num from other table after joining. I am trying REGEXP_SUBSTR(A.SRC_TXT, '(?<=CK#)(.+?\b)') = C.CHK_NUM in the where condition. I am getting the error as 'No repititive argument after ?'
You can use a regex for this
-- To remove just the character after a ~
select regexp_replace('fo~o bar','~.', '');
-- returns 'fo bar'
--If you want to keep the ~
select regexp_replace('fo~o bar','~.', '~');
-- returns 'fo~ bar'
--If you want to remove everything after the ~
select regexp_replace('fo~o bar','~.*', '');
--returns 'fo'
If you need to remove other specific character sets after a ~, you can probably do this with a slightly more complicated regex, but I'd need examples of your desired input/output to help with that.
EDIT for updated question
This regex replace should get what you need.
select regexp_replace('CK#123456~fndkjfgdjkg','CK#(\\d*)~.*', '\\1');
-- returns 123456
(\\d*) gets ANY number of digits in a row, and the \\1 causes it to replace the match with what was in the first set of parenthesis, which is your list of digits. the CK# and ~.* are there to make sure the whole string gets matched and replaced.
If the CK# can vary as well, you can use .*? like this.
select regexp_replace('ABCD123HI#123456~fndkjfgdjkg','.*?#(\\d*)~.*', '\\1')
-- returns 123456
I'd probably do something like the following, easy enough but not as cool as RegEx type of functions.
set my_string='fooo~12345';
set search_for_me = '~';
SELECT SUBSTR($my_string, 1, DECODE(position($search_for_me, $my_string), 0, length($my_string), position($search_for_me, $my_string)));
I hope this helps...Rich
It looks like lookahead and lookbehinds are not supported in REGEXP functions, they seem to work in the PATTERN clause of a LIST command. Snowflake documentation makes no mention either way of lookahead or lookbehinds.
In your example:
It seems that the query engine is looking for that repeating argument, where you are attempting a lookbehind
You have not specified what you wanted extracted. You have two capture groups, but in this scenario everything would be returned
Since you are looking to remove everything after ~ you have a delimiter, why not use it in your REGEXP_SUBSTR function?
Try the following:
SELECT $1,REGEXP_SUBSTR($1,'\\w+#(.+?)~',1,1,'is',1)
FROM VALUES
('CK#123456~fndkjfgdjkg')
,('QH#128fklj924~fndkjfgdjkg')
;
This looks for:
One or more word characters
Followed by #
Capturing one or more characters upto and not including ~
Returns the characters within the capture group
You can change the .+? to \\d+? to make sure the pattern is only digits. Backslashes must be escaped with a backslash.
The descriptions for each argument of the function can be found here:
https://docs.snowflake.net/manuals/sql-reference/functions/regexp_substr.html
You could check this!!
select substr('CK#123456~fndkjfgdjkg',4,6) from dual;
OUTPUT
123456
https://docs.snowflake.net/manuals/sql-reference/functions/substr.html

replace all occurrences of a sub string between 2 charcters using sql

Input string: ["1189-13627273","89-13706681","118-13708388"]
Expected Output: ["14013627273","14013706681","14013708388"]
What I am trying to achieve is to replace any numbers till the '-' for each item with hard coded text like '140'
SELECT replace(value_to_replace, '-', '140')
FROM (
VALUES ('1189-13627273-77'), ('89-13706681'), ('118-13708388')
) t(value_to_replace);
check this
I found the right way to achieve that using the below regular expression.
SELECT REGEXP_REPLACE (string_to_change, '\\"[0-9]+\\-', '140')
You don't need a regexp for this, it's as easy as concatenation of 140 and the substring from - (or the second part when you split by -)
select '140'||substring('89-13706681' from position('-' in '89-13706681')+1 for 1000)
select '140'||split_part('89-13706681','-',2)
also, it's important to consider if you might have instances that don't contain - and what would be the output in this case
Use regexp_replace(text,text,text) function to do so giving the pattern to match and replacement string.
First argument is the value to be replaced, second is the POSIX regular expression and third is a replacement text.
Example
SELECT regexp_replace('1189-13627273', '.*-', '140');
Output: 14013627273
Sample data set query
SELECT regexp_replace(value_to_replace, '.*-', '140')
FROM (
VALUES ('1189-13627273'), ('89-13706681'), ('118-13708388')
) t(value_to_replace);
Caution! Pattern .*- will replace every character until it finds last occurence of - with text 140.

Get string after '/' character

I want to extract the string after the character '/' in a PostgreSQL SELECT query.
The field name is source_path, table name is movies_history.
Data Examples:
Values for source_path:
184738/file1.mov
194839/file2.mov
183940/file3.mxf
118942/file4.mp4
And so forth. All the values for source_path are in this format
random_number/filename.xxx
I need to get 'file.xxx' string only.
If your case is that simple (exactly one / in the string) use split_part():
SELECT split_part(source_path, '/', 2) ...
If there can be multiple /, and you want the string after the last one, a simple and fast solution would be to process the string backwards with reverse(), take the first part, and reverse() again:
SELECT reverse(split_part(reverse(source_path), '/', 1)) ...
Or you could use the more versatile (and more expensive) substring() with a regular expression:
SELECT substring(source_path, '[^/]*$') ...
Explanation:
[...] .. encloses a list of characters to form a character class.
[^...] .. if the list starts with ^ it's the inversion (all characters not in the list).
* .. quantifier for 0-n times.
$ .. anchor to end of string.
db<>fiddle here
Old sqlfiddle
You need use substring function
SQL FIDDLE
SELECT substring('1245487/filename.mov' from '%/#"%#"%' for '#');
Explanation:
%/
This mean % some text and then a /
#"%#"
each # is the place holder defined in the last part for '#' and need and aditional "
So you have <placeholder> % <placeholder> and function will return what is found inside both placeholder. In this case is % or the rest of the string after /
FINAL QUERY:
SELECT substring(source_path from '%/#"%#"%' for '#');
FROM movies_history
you can use the split_part string function,
syntax: split_part(string,delimiter,position)
string example: exx = "2022-06-12"
Note: can be "#ertl/eitd/record_4" etc
delimiter: any character for the above example ("-" or "/")
Position: nth position,
How it works: the above exx string will be split in x times based on the delimiter
e.g position 1- 2022, position 2-06, position 3-12
so the nth position helps choose what you want to return
thus based on your example:
syntax: slipt_part(random_number/filename.xxx,"/",2)
output: filename.xxx

Replacing a String between two anchor points

I am trying to find a way to replace the string in between two "anchor points" in my VARCHAR2 column.
These "anchors" are <? and ?> and I want to remove (replace with '') everything that is between those two symbols.
I've already tried playing around with the REPLACE() function, e.g. stuff like SELECT REPLACE(my_varchar2_column,'<? % ?>') FROM my_table; and using the % operator as a wildcard, but that didn't work. No error was thrown, but the result wasn't as expected, as in the the replace function interpreting the % literally and not as a wildcard.
Does anyone have an idea how to achieve a replacement like this?
Example for current content of the column:
text I want to keep <? cryptic stuff in betweeen ?> text I want to keep as well
By replacing everything in between <? and ?> I want to remove that whole passage from my columns text. Expected result is like this:
text I want to keep text I want to keep as well
You Can you use REGEXP_REPLACE functionality of ORACLE.
First Argument = The column which needs to be replaced.
Second Argument = the substring to search for replacement.
Third Argument = the text to be replaced ( NOTE : if we omit this argument, the matched substrings are deleted
SELECT
REGEXP_REPLACE('text I want to keep <? cryptic stuff in betweeen ?> text ','<\?.*\?>')
FROM DUAL
OUTPUT:
text I want to keep text
select substr( my_varchar2_column, 1, INSTR( my_varchar2_column, '') +2 ) from yourtable;
Would that do the trick? You find the position of the beginning and end tags with the INSTR function and use it to SUBSTR the values before and after the tags.