Parse column value based on delimeters - sql

Here is a sample of my data:
ABC*12345ABC
BCD*234()
CDE*3456789(&(&
DEF*4567A*B*C
Using SQL Server 2008 or SSIS, I need to parse this data and return the following result:
12345
234
3456789
4567
As you can see, the asterisk (*) is my first delimiter. The second "delimiter" (I use this term loosely) is when the sequence of numbers STOP.
So, basically, just grab the sequence of numbers after the asterisk...
How can I accomplish this?
EDIT:
I made a mistake in my original post. An example of another possible value would be:
XWZ*A12345%$%
In this case, I would like to return the following:
A12345
The value can START with an alpha character, but it will always END with a number. So, grab everything after the asterisk, but stop at the last number in the sequence.
Any help with this will be greatly appreciated!

You could do this with a little patindex and charindex trickery, like:
; with YourTable(col1) as
(
select 'ABC*12345ABC'
union all select 'BCD*234()'
union all select 'CDE*3456789(&(&'
union all select 'DEF*4567A*B*C'
union all select 'XWZ*A12345%$%'
)
select left(AfterStar, len(Leader) + PATINDEX('%[^0-9]%', AfterLeader) - 1)
from (
select RIGHT(AfterStar, len(AfterStar) - PATINDEX('%[0-9]%', AfterStar) + 1)
as AfterLeader
, LEFT(AfterStar, PATINDEX('%[0-9]%', AfterStar) - 1) as Leader
, AfterStar
from (
select RIGHT(col1, len(col1) - CHARINDEX('*', col1)) as AfterStar
from YourTable
) as Sub1
) as Sub2
This prints:
12345
234
3456789
4567
A12345

If you ignore that this is in SQL then the first thing that comes to mind is Regex:
^.*\*(.*[0-9])[^0-9]*$
The capture group there should get what you want. I don't know if SQL has a regex function.

Related

Extract Value from a string PostgreSQL

Simple Question
I have the following type of results in a string field
'Number=123456'
'Number=1234567'
'Number=12345678'
How do I extract the value from the string with regard that the value can change between 5-8 figures
So far I did this but I doubt that fits my requirement
SELECT substring('Size' from 8 for ....
If I can tell it to start from the = sign till the end that would help!
The likely simplest solution is to trim 7 leading characters with right():
right(str, -7)
Demo:
SELECT str, right(str, -7)
FROM (
VALUES ('Number=123456')
, ('Number=1234567')
, ('Number=12345678')
) t(str);
str | right
-----------------+----------
Number=123456 | 123456
Number=1234567 | 1234567
Number=12345678 | 12345678
You could use REPLACE:
SELECT col, REPLACE(col, 'Number=', '')
FROM tab;
DBFiddle Demo
Based on this question:
Split comma separated column data into additional columns
You could probably do the following:
SELECT *, split_part(col, '=', 2)
FROM table;
You may use regexp_matches :
with t(str) as
(
select 'Number=123456' union all
select 'Number=1234567' union all
select 'Number=12345678' union all
select 'Number=12345678x9'
)
select t.str as "String",
regexp_matches(t.str, '=([A-Za-z0-9]+)', 'g') as "Number"
from t;
String Number
-------------- ---------
Number=123456 123456
Number=1234567 1234567
Number=12345678 12345678
Number=12345678x9 12345678x9
--> the last line shows only we look chars after equal sign even if non-digit
Rextester Demo

How to remove only letters from a string in BigQuery?

So I'm working with BigQuery SQL right now trying to figure out how to remove letters but keep numeric numbers. For example:
XXXX123456
AAAA123456789
XYZR12345678
ABCD1234567
1111
2222
All have the same amount of letters in front of the numbers along with regular numbers no letters. I want the end result to look like:
123456
123456789
12345678
1234567
1111
2222
I tried using PATINDEX but BigQuery doesn't support the function. I've also tried using LEFT but that function will get rid of any value and I don't want to get rid of any numeric value only letter values. Any help would be much appreciated!
-Maykid
You can use regexp_replace():
select regexp_replace(str, '[^0-9]', '')
Below example is for BigQuery Standard SQL
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'XXXX123456' str UNION ALL
SELECT 'AAAA123456789' UNION ALL
SELECT 'XYZR12345678' UNION ALL
SELECT 'ABCD1234567' UNION ALL
SELECT '1111' UNION ALL
SELECT '2222'
)
SELECT str, REGEXP_REPLACE(str, r'[a-zA-Z]', '') str_adjusted
FROM `project.dataset.table`

Concatenate & Trim String

Can anyone help me, I have a problem regarding on how can I get the below result of data. refer to below sample data. So the logic for this is first I want delete the letters before the number and if i get that same thing goes on , I will delete the numbers before the letter so I can get my desired result.
Table:
SALV3000640PIX32BLU
SALV3334470A9CARBONGRY
TP3000620PIXL128BLK
Desired Output:
PIX32BLU
A9CARBONGRY
PIXL128BLK
You need to use a combination of the SUBSTRING and PATINDEX Functions
SELECT
SUBSTRING(SUBSTRING(fielda,PATINDEX('%[^a-z]%',fielda),99),PATINDEX('%[^0-9]%',SUBSTRING(fielda,PATINDEX('%[^a-z]%',fielda),99)),99) AS youroutput
FROM yourtable
Input
yourtable
fielda
SALV3000640PIX32BLU
SALV3334470A9CARBONGRY
TP3000620PIXL128BLK
Output
youroutput
PIX32BLU
A9CARBONGRY
PIXL128BLK
SQL Fiddle:http://sqlfiddle.com/#!6/5722b6/29/0
To do this you can use
PATINDEX('%[0-9]%',FieldName)
which will give you the position of the first number, then trim off any letters before this using SUBSTRING or other string functions. (You need to trim away the first letters before continuing with the next step because unlike CHARINDEX there is no starting point parameter in the PATINDEX function).
Then on the remaining string use
PATINDEX('%[a-z]%',FieldName)
to find the position of the first letter in the remaining string. Now trim off the numbers in front using SUBSTRING etc.
You may find this other solution helpful
SQL to find first non-numeric character in a string
Try this it may helps you
;With cte (Data)
AS
(
SELECT 'SALV3000640PIX32BLU' UNION ALL
SELECT 'SALV3334470A9CARBONGRY' UNION ALL
SELECT 'SALV3334470A9CARBONGRY' UNION ALL
SELECT 'SALV3334470B9CARBONGRY' UNION ALL
SELECT 'SALV3334470D9CARBONGRY' UNION ALL
SELECT 'TP3000620PIXL128BLK'
)
SELECT * , CASE WHEN CHARINDEX('PIX',Data)>0 THEN SUBSTRING(Data,CHARINDEX('PIX',Data),LEN(Data))
WHEN CHARINDEX('A9C',Data)>0 THEN SUBSTRING(Data,CHARINDEX('A9C',Data),LEN(Data))
ELSE NULL END AS DesiredResult FROM cte
Result
Data DesiredResult
-------------------------------------
SALV3000640PIX32BLU PIX32BLU
SALV3334470A9CARBONGRY A9CARBONGRY
SALV3334470A9CARBONGRY A9CARBONGRY
SALV3334470B9CARBONGRY NULL
SALV3334470D9CARBONGRY NULL
TP3000620PIXL128BLK PIXL128BLK

How to Extract the middle characters from a string without an specific index to start and end it before the space character is read?

I have a column that contains data like:
AB-123 XYZ
ABCD-456 AAA
BCD-789 BBB
ZZZ-963
Y-85
and this is what i need from those string:
123
456
789
963
85
I need the characters from the left after the dash('-') character, then ends before the space character is read.
Thank You guys.
Note: Original tag on this question was Oracle and this answer is based on that tag. Now that, tag is updated to SqlServer, this answer is no longer valid, if somebody looking for Oracle solution, this may help.
Use regular expression to arrive at sub string.
select trim(substr(regexp_substr('ABCD-456 AAA','-[0-9]+ '),2)) from dual
'-[0-9]+ ' will grab any string pattern which starts with dash has one or more digits and ends with a ' ' and returns number with dash
substr will remove '-' from above output
trim will remove any trailing ' '
Check This.
Using Substring and PatIndex.
select
SUBSTRING(colnm, PATINDEX('%[0-9]%',colnm),
PATINDEX('%[^0-9]%',ltrim(RIGHT(colnm,LEN(colnm)-CHARINDEX('-',colnm)))))
from
(
select 'AB-123 XYZ' colnm union
select 'ABCD-456 AAA' union
select 'BCD-789 BBB' union
select 'ZX- 23 BBB'
)a
OutPut :
Try this
http://rextester.com/YTBPQD69134
CREATE TABLE Table1 ([col] varchar(12));
INSERT INTO Table1
([col])
VALUES
('AB-123 XYZ'),
('ABCD-456 AAA'),
('BCD-789 BBB');
select substring
(col,
charindex('-',col,1)+1,
charindex(' ',col,1)-charindex('-',col,1)
) from table1;
Assume all values has '-' and followed by a space ' '. Below solution will not tolerant to exception case:
SELECT
*,
SUBSTRING(Value, StartingIndex, Length) AS Result
FROM
-- You can replace this section of code with your table name
(VALUES
('AB-123 XYZ'),
('ABCD-456 AAA'),
('BCD-789 BBB')
) t(Value)
-- Use APPLY instead of sub-query is for debugging,
-- you can view the actual parameters in the select
CROSS APPLY
(
SELECT
-- Get the first index of character '-'
CHARINDEX('-', Value) + 1 AS StartingIndex,
-- Get the first index of character ' ', then calculate the length
CHARINDEX(' ', Value) - CHARINDEX('-', Value) - 1 AS Length
) b

PLSQL show digits from end of the string

I have the following problem.
There is a String:
There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235
I need to show only just the last date from this string: 2015.06.07.
I tried with regexp_substr with insrt but it doesn't work.
So this is just test, and if I can solve this after it with this solution I should use it for a CLOB query where there are multiple date, and I need only the last one. I know there is regexp_count, and it is help to solve this, but the database what I use is Oracle 10g so it wont work.
Can somebody help me?
The key to find the solution of this problem is the idea of reversing the words in the string presented in this answer.
Here is the possible solution:
WITH words AS
(
SELECT regexp_substr(str, '[^[:space:]]+', 1, LEVEL) word,
rownum rn
FROM (SELECT 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 2015.06.08 2015.06.17. 2015.07.01. 12345678999 12125235' str
FROM dual) tab
CONNECT BY LEVEL <= LENGTH(str) - LENGTH(REPLACE(str, ' ')) + 1
)
, words_reversed AS
(
SELECT *
FROM words
ORDER BY rn DESC
)
SELECT regexp_substr(word, '\d{4}\.\d{2}\.\d{2}', 1, 1)
FROM words_reversed
WHERE regexp_like(word, '\d{4}\.\d{2}\.\d{2}')
AND rownum = 1;
From the documentation on regexp_substr, I see one problem immediately:
The . (period) matches any character. You need to escape those with a backslash: \. in order to match only a period character.
For reference, I am linking this post which appears to be the approach you are taking with substr and instr.
Relevant documentation from Oracle:
INSTR(string , substring [, position [, occurrence]])
When position is negative, then INSTR counts and searches backward from the end of string. The default value of position is 1, which means that the function begins searching at the beginning of string.
The problem here is that your regular expression only returns a single value, as explained here, so you will be giving the instr function the appropriate match in the case of multiple dates.
Now, because of this limitation, I recommend using the approach that was proposed in this question, namely reverse the entire string (and your regular expression, i.e. \d{2}\.\d{2}\.\d{4}) and then the first match will be the 'last match'. Then, perform another string reversal to get the original date format.
Maybe this isn't the best solution, but it should work.
There are three different PL/SQL functions that will get you there.
The INSTR function will identify where the first "period" in the date string appears.
SUBSTR applied to the entire string using the value from (1) as the start point
TO_DATE for a specific date mask: YYYY.MM.DD will convert the result from (2) into a Oracle date time type.
To make this work in procedural code, the standard blocks apply:
DECLARE
v_position pls_integer;
... other variables
BEGIN
sql code and function calls;
END
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE finddate
(column1 varchar2(11), column2 varchar2(39))
;
INSERT ALL
INTO finddate (column1, column2)
VALUES ('row1', '1234567 242424 2015.06.07. 12125235')
INTO finddate (column1, column2)
VALUES ('string2', '1234567 242424 2015.06.07. 12125235')
SELECT * FROM dual
;
Query 1:
select instr(column2,'.',1) from finddate
where column1 = 'string2'
select substr(column2,(20-4),10) from finddate
select to_date('2015.06.07','YYYY.MM.DD') from finddate
Results:
| TO_DATE('2015.06.07','YYYY.MM.DD') |
|------------------------------------|
| June, 07 2015 00:00:00 |
| June, 07 2015 00:00:00 |
Here's a way using regexp_replace() that should work with 10g, assuming the format of the lines will be the same:
with tbl(col_string) as
(
select 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235'
from dual
)
select regexp_replace(col_string, '^.*(\d{4}\.\d{2}\.\d{2})\. \d*$', '\1')
from tbl;
The regex can be read as:
^ - Match the start of the line
. - followed by any character
* - followed by 0 or more of the previous character (which is any character)
( - Start a remembered group
\d{4}\.\d{2}\.\d{2} - 4 digits followed by a literal period followed by 2 digits, etc
) - End the first remembered group
\. - followed by a literal period
- followed by a space
\d* - followed by any number of digits
$ - followed by the end of the line
regexp_replace then replaces all that with the first remembered group (\1).
Basically describe the whole line as a regular expression, group around what you want to return. You will most likely need to tweak the regex for the end of the line if it could be other characters than digits but this should give you an idea.
For the sake of argument this works too ONLY IF there are 2 occurrences of the date pattern:
with tbl(col_string) as
(
select 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235' from dual
)
select regexp_substr(col_string, '\d{4}\.\d{2}\.\d{2}', 1, 2)
from tbl;
returns the second occurrence of the pattern. I expect the above regexp_replace more accurately describes the solution.