SQL Server 2012 Removing part of string before and after specific, repeating character - sql

Would you please assist with a perplexing string operator problem?
I need to parse a NVARCHAR(32), not null column called MachineName from table dbo.Log. The format is either:
AA-BBB-CCC-DDD
AA-BBB-CCCC-DDD
AA-BBB-CCC-DDDD
AA-BBB-CCCC-DDDD
I need the Result Set (as [Code]) to be either CCC or CCCC.
I consulted this article:
http://basitaalishan.com/2014/02/23/removing-part-of-string-before-and-after-specific-character-using-transact-sql-string-functions/
With this code:
SELECT DISTINCT [MachineName]
,REPLACE(SUBSTRING([MachineName], CHARINDEX('-', [MachineName],6), LEN([MachineName])), '-', '') AS [Code]
FROM [dbo].[Log]
My current Result Set is fine on the left, but the right needs refinement.
CCCDDD
CCCCDDDD
I would defintely appreciate your help! Thank you in advance

You can improvise on this: http://sqlfiddle.com/#!3/9eecb7d/588
with test as (
select cast('AA-BBB-CCC-DDD' as nvarchar(32)) as field1
union all
select cast('AA-BBB-CCCC-DDD' as nvarchar(32)) as field1
union all
select cast('AA-BBB-CCC-DDDD' as nvarchar(32)) as field1
union all
select cast('AA-BBB-CCCC-DDDD' as nvarchar(32)) as field1
)
select
substring(
substring(field1,8,32),
1,
charindex('-', substring(field1,8,32))-1
)
from test
Result:
CCC
CCCC
CCC
CCCC
With substring, we ignore the first 7 characters and start with 8th character. That'll give us CCCC-DDD and such. charindex will tell us the position of - in CCCC-DDD and such. We reapply substring on the substring; starting with first position and capturing all up until - was found.
In your case, you could do:
select distinct
substring(
substring(MachineName,8,32),
1,
charindex('-', substring(MachineName,8,32))-1
) as Code
from dbo.Log

Related

Remove everything after a specific special character in SQL Server

This Question is pretty much answered in this forum but for my situation which is exactly the same the answers I find here are not working.
I'm trying to remove all the characters after the pipe " | " in sql server. Any suggestions why it's not working?
query that i'm using:
SELECT left(name, charindex('|',name) -1) from table1
Error:
Invalid length parameter passed to the LEFT or SUBSTRING function.
table1:
name
----
jack| rose|
wil |jo|rdy
karl||jay
jo smith
jjill
raj |kumar
Desired output:
name
----
jack
wil
karl
jo smith
jjill
raj
try:
select LEFT(name,CHARINDEX('|',name + '|')-1)
from table1
Think you're almost there - you just need to filter to ensure you aren't passing a negative number to the LEFT
e.g.,
SELECT left(name, charindex('|',name) -1) from table1
WHERE name LIKE '%|%'
Remember charindex is 0 if it doesn't exist in string, then you subtract 1. This means you're trying to do a LEFT(name, -1) which is invalid.
To get your full output (with all rows, regardless of the | symbol) you can use it in a CASE instead.
SELECT CASE
WHEN [name] LIKE '%|%' THEN left(name, charindex('|',name) -1)
ELSE [name] END AS [name]
from table1
Edit: Here's a db<>fiddle with results.
You can try the below -
SELECT left(name, case when charindex('|',name)=0 then len(name)
else charindex('|',name)-1 end),charindex('|',name)
from tablename
based on your query, its expecting values to have | always. So this will error on name = jo smith'. Use select case to solve this.
declare #str varchar(200)
set #str = 'jo smith'
select case when charindex('|',#str) > 0 then left(#str, charindex('|',#str) -1) else #str end
Instead of using LEFT, use a combination of STUFF and ISNULL.
While LEFT will raise the "Invalid length parameter passed to the left function." error if it gets a negative length parameter,
STUFF will simply return null if it's starting position argument is less than less than 1.
This means that if the original value doesn't contain | and charindex return 0, stuff will simply return null, and you can use ISNULL to return the original value in this case.
First, create and populate sample table (Please save us this step in your future questions):
DECLARE #T TABLE (
[name] varchar(20)
);
INSERT INTO #T ([name]) VALUES
('jack| rose|'),
('wil |jo|rdy'),
('karl||jay'),
('jo smith'),
('jjill'),
('raj |kumar');
The query:
SELECT [name],
ISNULL(STUFF([name], CHARINDEX('|', [name]), LEN([name]), ''), [name]) As Replaced
FROM #T
Results:
name Replaced
jack| rose| jack
wil |jo|rdy wil
karl||jay karl
jo smith jo smith
jjill jjill
raj |kumar raj

T-SQL splitting column on a delimiter [duplicate]

This question already has answers here:
T-SQL split string
(27 answers)
Closed 4 years ago.
I have a column with three groups data delimited by a forward slash, like so
AB/1234/10
The column is always formatted the same in every row, with 2 characters, a slash, some number of characters, a slash, and then 2 more characters. I need to split this one column into three. So the above example becomes
Column1 Column2 Column3
AB 1234 10
I'm not quite sure how to go about this. I've been using SELECT SUBSTRING but that isn't quite giving me what I need.
select SUBSTRING(MyColumn, 1, CHARINDEX('/', MyColumn, 1)-1)
FROM MyTable
Will return AB, and that's great. But I can't wrap my mind around how to grab the middle and the end sections. I thought that
select SUBSTRING(MyColumn, 4, CHARINDEX('/', MyColumn, 4))
FROM MyTable
Would work in grabbing the middle, but it returns 1234/10
I hope my question is clear and I would appreciate any advice pointing me in the right direction, Thank you.
You can work with fixed offsets, since you defined that the string always starts with two, and ends with two characters.
Here is a full working example:
DECLARE #tmp TABLE (
Merged nvarchar(max)
)
INSERT INTO #tmp SELECT N'AB/1234/10'
INSERT INTO #tmp SELECT N'AB/ANYNUMBEROF-CHARACTERS/10'
SELECT
LEFT(Merged,2) AS Column1,
SUBSTRING(Merged,4,LEN(Merged)-6) AS Column2,
RIGHT(Merged,2) AS Column3
FROM #tmp
We subtract the length of the string minus a constant (6 = two chars left, two chars right, two slashes) to extract the variable-length part from the middle.
Result:
Column1 Column2 Column3
AB 1234 10
AB ANYNUMBEROF-CHARACTERS 10
One approach is to use PARSENAME:
SELECT PARSENAME(REPLACE('AB/1234/10','/','.'), 3) Col1,
PARSENAME(REPLACE('AB/1234/10','/','.'), 2) Col2,
PARSENAME(REPLACE('AB/1234/10','/','.'), 1) Col3
This will replace the / with ., and pull out each section of the string with PARSENAME.
The benefit is that it will work with any length of characters in any position. The limits is that PARSENAME only handles up to 4 positions (in this case you are using 3), and will fail if periods . exist in the string already.
Try this. This should work with any number of characters.
DECLARE #str VARCHAR(100) = 'AB/1234/10'
SELECT LEFT(#str, CHARINDEX('/', #str) - 1) AS Column1
, SUBSTRING(#str, CHARINDEX('/', #str) + 1, CHARINDEX('/', SUBSTRING(#str, CHARINDEX('/', #str) + 1, LEN(#str))) - 1) AS Column2
, RIGHT(#str, CHARINDEX('/', REVERSE(#str)) - 1) AS Column3

SQL Server select part of string

I have table like this
Column1
-------------------------------------------------------
nn=APPLE IPod 44454,o=0006,o=TOP8,nn=USA,nn=TOP8+
nn=SAMSUNG G5 487894,o=04786,o=T418,nn=JPN,nn=TO478+
And I need update that table and get result like this
Column1 Column2
---------------------------------------------------------------
nn=APPLE IPod 44454,o=0006,o=TOP8,nn=USA,nn=TOP8+ 44454
nn=SAMSUNG G5 487894,o=04786,o=T418,nn=JPN,nn=TO478+ 487894
My idea is but I can not fit with first character:
update tablename
set [column2] = SUBSTRING(column1, 1, CHARINDEX(' ', column1) - 1 (column1, CHARINDEX(' ', column1) + 1, LEN(column1))
This query can help you.
UPDATE tablename SET [column2] =
SUBSTRING((LEFT(column1,CHARINDEX(',',column1)-1)), CHARINDEX(' ', column1, CHARINDEX(' ',column1) +1 ) +1 ,LEN(column1))
Okay, given the second sample record, it looks like what you need is the last element of the space-delimited string in the first position of the comma-delimited string. So write yourself (or find) a string-splitter function that accepts a string and a delimiter, and then your parsing logic is:
split the field at the commas
take the first element
split that element at the spaces
take the last element
Does that make sense?
The following answer is based only on the two records you actually showed us. If we were to derive a rule from this, it might be that we want to extract the previous word (a product number) occurring immediately before the first comma in the string. If so, then we can try the following logic:
isolate the substring before the comma (e.g. nn=APPLE Ipod 44454)
reverse that string (45444 dopI ELPPA=nn)
then take the substring of that before the first space (45444)
finally reverse this substring to yield the product number we want (44454)
Consider the following query, with data imported via a CTE:
WITH yourTable AS (
SELECT 'nn=APPLE IPod 44454,o=0006,o=TOP8,nn=USA,nn=TOP8+' AS column1 UNION ALL
SELECT 'nn=SAMSUNG G5 487894,o=04786,o=T418,nn=JPN,nn=TO478+'
),
update_cte AS (
SELECT
column1,
column2,
REVERSE(
SUBSTRING(REVERSE(SUBSTRING(column1, 1, CHARINDEX(',', column1)-1)),
1,
CHARINDEX(' ', REVERSE(SUBSTRING(column1, 1, CHARINDEX(',', column1)-1))) - 1)
) AS col2
FROM yourTable
)
SELECT column1, col2 FROM update_cte;
Output:
Demo here:
Rextester
If you wanted to update your table to bring in these column2 product IDs, then you can use the above CTE fairly easily:
UPDATE update_cte
SET column2 = col2;

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

Parse column value based on delimeters

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.