select statement to display desired output - sql

I have a column in table with values similar to this:
key_value
eg:
3933984948498934_khkhk
81299191ahgtyu092092092019_92982
abh182772hjjlj98879bjj_122778999
_ is common in all the values. I need a script to copy some portion of the value i.e. copy everything before _ and not display anything after _ for all the values in that column.
I need a select statement to display output as mentioned above.
eg: Actual value is 3933984948498934_khkhk but I need just 3933984948498934
Actual value 81299191ahgtyu092092092019_92982 but desired output is 81299191ahgtyu092092092019.
I feel using substr function is cumbersome as the values are dynamic.

You could use a regular expression, e.g.:
SELECT REGEXP_SUBSTR(key_value, '^[^_]*')
FROM mytable;
but regular expressions are resource-intensive; you'd be better served using SUBSTR() and INSTR():
SELECT SUBSTR(key_value, 1, INSTR(key_value, '_') - 1)
FROM mytable;
Note that this latter method will fail (actually, it will return NULL) if key_value does not contain an underscore _. So you might wrap it in COALESCE():
SELECT COALESCE(SUBSTR(key_value, 1, INSTR(key_value, '_') - 1), key_value)
FROM mytable;

Related

SQL - Grabbing only a portion of the message in a each row

I have a column name "value" in table T with a long description of errors, it has here is an example of few
but it is also grabbing other rows which i don't need.
Please help?
This answers the original version of the question.
To filter the rows, use regexp_like(). I would suggest:
select t.*
from t
where regexp_like(value, '^An image has error at (1203|12345):')
I am guessing that the final colon is important for the matching.
Why can't you use the LIKE operator?
SELECT t.id, t.value, SUBSTR(t.value, 1, INSTR(t.value, ':')) short_value
FROM t
WHERE value LIKE 'An image has error at 1203:%'
OR value LIKE 'An image has error at 12345:%';
Perhaps your best option seems is a combination of a standard substr+instr to extract the desired value with a regexp_like to determine overall string t desirability overall string.
select substr(value, 1, instr(value, ':')-1 ) value
from d
where regexp_like (value,'An image has error at \d+:');
Although depending the exact requirement for leading test requirement and following numeric value perhaps just
select substr(value, 1, instr(value, ':')-1 ) value
from d
where instr(value, ':') > 1;
Finally you can stay with regexp_substr if you wish. However, Oracle's syntax for that is totally counter intuitive to use of regular expressions:
select value
from (select regexp_substr(value, '(.*):', 1, 1, 'i', 1) value
from d
)
where value is not null;
Demo

SQL String split and update field

I have table Project with a column name Name with values in the format SYS_12345_Value. I want to update this Name field such that its value in every row is replaced by the term after second _ in its value.
At the moment it looks like SYS_82058_INDIGO and I want to replace it with INDIGO and the same for all the rows in the table.
Any help is appreciated. Thanks alot.
UPDATE : Tried #GordonLinoff's solution as follows
UPDATE Project
SET Name = (select right(str, charindex('_', reverse(str)) - 1) from (values (Name)) v(str))
WHERE Name like '%SYS%'
String manipulation in SQL Server is usually tricky. But if you want the last component, you can use:
select *,
right(str, charindex('_', reverse(str)) - 1)
from (values ('SYS_82058_INDIGO')) v(str)
Use a couple of nested CHARINDEX functions. This assumes that every row has 2 underscore (_) characters:
UPDATE dbo.YourTable
SET YourColumn = STUFF(YourColumn,1,CHARINDEX('_',YourColumn,CHARINDEX('_',YourColumn)+1),'');

TSQL extract part of string with regex

i would make a script that iterate over the records of a table with a cursor
and extract from a column value formatted like that "yyy://xx/bb/147011"
only the final number 147011and to put this value in a variable.
It's possible to do something like that?
Many thanks.
You don't need a cursor for this. You can just use a query. The following gets everything after the last /:
select right(str, charindex('/', reverse(str)) - 1 )
from (values ('yyy://xx/bb/147011')) v(str)
It does not specifically check if it is a number, but that can be added as well.
You can also use the below query.
SELECT RIGHT(RTRIM('yyy://xx/bb/147011'),
CHARINDEX('/', REVERSE('/' + RTRIM('yyy://xx/bb/147011'))) - 1) AS LastWord
If numeric value has exact position defined with sample data, then you can do :
SELECT t.*, SUBSTRING(t.col, PATINDEX('%[0-9]%', t.col), LEN(t.col))
FROM table t;

How to get file name without extension with using Regular Expressions

I have a field with following values, now i want to extract only those rows with "xyz" in the field value mentioned below, can you please help?
Mydata_xyz_aug21
Mydata2_zzz_aug22
Mydata3_xyz_aug33
One more requirement
I want to extract only "aIBM_MyProjectFile" from following string below, can you please help me with this?
finaldata/mydata/aIBM_MyProjectFile.exe.ld
I've tried this but it didn't work.
select
regexp_substr('FinalProject/MyProject/aIBM_MyProjectFile.exe.ld','([^/]*)[\.]') exp
from dual;
To extract substrings between the first pair of underscores, you need to use
regexp_substr('Mydata_xyz_aug21','_([^_]+)_', 1, 1, NULL, 1)
To get the file name without the extension, you need
regexp_substr('FinalProject/MyProject/aIBM_MyProjectFile.exe.ld','.*/([^.]+)', 1, 1, NULL, 1)
Note that each regex contains a capturing group (a pattern inside (...)) and this value is accessed with the last 1 argument to the regexp_substr function.
The _([^_]+)_ pattern finds the first _, then places 1 or more chars other than _ into Group 1 and then matches another _.
The .*/([^.]+) pattern matches the whole text up to the last /, then captures 1 or more chars other than . into Group 1 using ([^.]+).
For the first requirement, it would suffice to use LIKE, as posted in answer above:
SELECT column
FROM table
WHERE column LIKE '%xyz%';
For your second requirement (extraction) you will have to use REGEXP_SUBSTR function:
SELECT REGEXP_SUBSTR ('FinalProject/MyProject/aIBM_MyProjectFile.exe.ld', '.*/([^.]+)', 1, 1, NULL, 1)
FROM DUAL
I hope it helped!
Another way to do this is to skip regexp completely:
WITH
aset AS
(SELECT 'with_extension.txt' txt FROM DUAL
UNION ALL
SELECT 'without_extension' FROM DUAL)
SELECT CASE
WHEN INSTR (txt, '.', -1) > 0
THEN
SUBSTR (txt, 1, INSTR (txt, '.', -1) - 1)
ELSE
txt
END
txt
FROM aset
The result of this is
with_extension
without_extension
A BIG Caveat where the regexp is better:
My method doesn't handle this case correctly:
\this\is.a\test
So after I have gone to all this effort, stay with the regexp solutions. I'll leave this here so that others may learn from it.

How to remove zeros from a column in db2 table

I have a column with data zeros after 6th column
i want to remove the leading zero after the 6th pipe in the data.
Please let me know if there is any way to do it. I tried to use substr with Trim but its not working.
Let's say your column is called COL something like the following should work:
CONCAT(SUBSTR(1,INSTR(COL,'|', 1,5)), LTRIM(SUBSTR(INSTR(COL,'|', 1,5)+1)),'0'))
Assuming from your current data that you need to only replace every occurrence of |00 with |, You can achieve thing using REPLACE function.
SELECT 'TMB|MLE020828585|74384911WA3S|="''07300058"|74384911|0013' AS Current_String,
replace('TMB|MLE020828585|74384911WA3S|="''07300058"|74384911|0013', '|00', '|') AS result_String
You can replace hard-coded value in above with your column name.
The above query generate result as below.
Current_String | result_String
------------------------------------------------------------------------------------------------------------------------
TMB|MLE020828585|74384911WA3S|="'07300058"|74384911|0013 | TMB|MLE020828585|74384911WA3S|="'07300058"|74384911|13
Hope this will help.
Oleg was correct in utilizing INSTR(), that is how I would do it. He was missing some arguments, though. Also, I wasn't able to get ltrim to work, so I cast it to an int instead. I tested and updated my table with your data using:
UPDATE mytable
SET mycolumn = Substr(mycolumn , 1, Instr(mycolumn , '|', 1, 5))
|| CAST(Substr(mycolumn , Instr(mycolumn , '|', 1, 5) + 1) AS INT)