Find values in between two characters '(' and ')' in column that have nulls - sql

I have a table name authors. I need to extract the values at the end of their names excluding '(' and ')'.
I have tried to use a substring with Charindex function.
select
isnull (SUBSTRING(name,CHARINDEX('(',name) +1 ,CHARINDEX(')',name) - CHARINDEX('(',name) - 1), '') as [Name]
from Authors
But I got an error message.
Msg 537, Level 16, State 3, Line 6
Invalid length parameter passed to the LEFT or SUBSTRING function.
Here is what I am expecting my results to be.

For your data, I would do something like this:
select coalesce(replace(stuff(name, 1, charindex('(', name + '(') + 1, ''), ')', ''),
'') as [Name]
This assumes that the parentheses are at the end of the string, as in the examples.

declare #string nvarchar(25)
set #string = '(asdfgh)'
select REPLACE( REPLACE(#string,'(',''),')','') where #string like '%[(]%%[)]%'
in above code i used regex to find string between ( and ) then replace them by empty

here you go, apply to your situation
declare #string varchar(25)
set #string = '(asdfgh)'
SELECT SUBSTRING(#string,
charindex('(', #string)+1,
charindex(')', #string)-
charindex('(', #string)-1)

You can use APPLY :
select substring(name, tt.startp + 1, (endp - startp) - 1) as Name
from Authors a cross apply
( values (charindex('(', name + ')'), charindex(')', name + ')'))
) tt(startp, endp);
Your Name column doesn't have a (...) in some places so, you can add either where clause or add explicitly (...) at the end of string.

Related

How to get the middle word using Substring via Charindex of Second Position?

Basically what I am trying to do is that I want to get the middle word, using the second occurrence of the same character (on this case, dash "-").
This is the sample input:
declare #word nvarchar(max)
set #word = 'Technical Materials - Conversion - Team Dashboard'
There are three parts on this sentence, and they are divided by '-' dash line.
The first part is 'Technical Materials' which I am able to get using:
SELECT LTRIM(RTRIM(SUBSTRING(#word, 0, CHARINDEX('-', #word, 0))))
The last set was 'Team Dashboard' which I am able to get using:
SELECT CASE WHEN LEN(#word) - LEN(REPLACE(#word, '-', '')) = 1
THEN NULL
ELSE
RIGHT(#word,CHARINDEX('-', REVERSE(#word))-1)
END
The problem was, I am having a hard time getting the middle words which is 'Conversion' in this example.
If the format is fixed, you can use PARSENAME to achieve your expectation:
DECLARE #Word AS NVARCHAR(MAX) = 'Technical Materials - Conversion - Team Dashboard'
SELECT PARSENAME(REPLACE(#Word, '-', '.'), 2)
if you want to trim the extra spaces, then:
SELECT LTRIM(RTRIM(PARSENAME(REPLACE(#Word, '-', '.'), 2)))
Try this query:
SELECT
SUBSTRING(#word,
CHARINDEX('-', #word) + 2,
CHARINDEX('-', #word, CHARINDEX('-', #word) + 1) -
CHARINDEX('-', #word) - 3)
FROM yourTable
The general strategy here is to use SUBSTRING(), which requires the starting and ending positions of the middle string in question. We can use CHARINDEX to find both the first and second dash in the string. From this, we can compute the positions of the middle substring we want.
Demo here:
Rextester
This will find the text between the first 2 occurrences of '-'
DECLARE #word nvarchar(max)
SET #word = 'Technical Materials - Conversion - Team Dashboard'
SELECT SUBSTRING(x, 0, charindex('-', x))
FROM (values(stuff(#word, 1, charindex('-', #word), ''))) x(x)
This will find the middle element. In case of an even number of elements it will pick the first of the 2 middle elements
DECLARE #word nvarchar(max)
SET #word = 'Technical Materials - Conversion - Team Dashboard'
;WITH CTE(txt, rn, cnt) as
(
SELECT
t.c.value('.', 'VARCHAR(2000)'),
row_number() over (order by (select 1)), count(*) over()
FROM (
SELECT x = CAST('<t>' +
REPLACE(#word, ' - ', '</t><t>') + '</t>' AS XML)
) a
CROSS APPLY x.nodes('/t') t(c)
)
SELECT txt
FROM CTE
WHERE (cnt+1) / 2 = rn

Select only characters in SQL

I have strings in a database like this:
firstname.lastname#email.com
And I only need the characters that appear after the # symbol and before (.) symbol i.e. (email) from the above example
I am trying to find a simple way to do this in SQL.
Do this:
use [your_db_name];
go
create table dbo.test
(
string varchar(max) null
)
insert into dbo.test values ('firstname.lastname#email.com')
select
string,
substring(
string,
charindex('#', string, 0) + 1,
charindex('.', string, charindex('#', string, 0)) - charindex('#', string, 0) - 1
) as you_need
from dbo.test
String manipulations are such a pain in SQL Server. Here is one method:
select t.*,
left(en.emailname, charindex('.', en.emailname + '.') - 1)
from t outer apply
(select stuff(email, 1, charindex('#', email + '#'), '') as emailname) en;
That that in the charindex() calls, the character being searched for is placed at the end of the string. This allows the code to work even for malformed emails -- it returns an empty string when the email is not of the form '%#%.%'.
DECLARE #col char(200)
set #col = 'firstname.lastname#email.com'
SELECT SUBSTRING(#col, LEN(LEFT(#col, CHARINDEX ('#', #col))) + 1, LEN(#col) - LEN(LEFT(#col, CHARINDEX ('#', #col))) - LEN(RIGHT(#col, LEN(#col) - CHARINDEX ('.', #col))) - 4);
DECLARE #str varchar(50) = 'firstname.lastname#email.com';
SELECT LEFT(
RIGHT(#str, LEN(#str) - CHARINDEX('#', #str))
,CHARINDEX('.', RIGHT(#str, LEN(#str) - CHARINDEX('#', #str))
) - 1) AS OUTPUT
Above query gives only domain-name from Email. The query can be applied for column in a table
Try This:-
DECLARE #Text varchar(100)
SET #Text = 'firstname.lastname#email.com'
SELECT SUBSTRING(STUFF(#Text, 1, CHARINDEX('#',#Text), ''), 0,
CHARINDEX('.', STUFF(#Text, 1, CHARINDEX('#',#Text), '')))
Result:-
email
DECLARE #myStr varchar(100) = 'firstname.lastname#email.com'
SELECT
SUBSTRING(SUBSTRING(#myStr,CHARINDEX('#',#myStr)+1,LEN(#myStr)-CHARINDEX('#',#myStr)+1),0,CHARINDEX('.',SUBSTRING(#myStr,CHARINDEX('#',#myStr)+1,LEN(#myStr)-CHARINDEX('#',#myStr)+1)))
That can be useful but I really recommend you to build user defined function in C#/Visaul basic they could be much more faster that this.
Using charindex, len and reverse to search for the positions of the # and the last dot.
And substring to get the name based on those positions:
create table test (id int identity(1,1), email varchar(60));
insert into test (email) values
('jane.doe#email.com'),
('not an email'),
('#invalid.email.xxx'),
('john.doe#longer.domainname.net');
select *,
(case
when email like '[a-z]%#%.%'
then substring(email,
charindex('#',email)+1,
len(email) - charindex('#',email) - charindex('.',reverse(email))
)
end) as email_domain_without_extension
from test;
The CASE WHEN is used to return NULL when it's not an email (instead of an empty string).

Return a SUBSTRING with a known Prefix and Suffix Character

I have a table that has a Prefix of variable length that always ends with . and a suffix of variable length that always begins with -. The - can also be found in the string of text that I am looking for, so using REVERSE() is likely the best way to identify the suffix -.
ex: Prefix1.ABC-123-Suffix1
I'd like the SUBSTRING() result to look like: ABC-123
I was able to create both a SUBSTRING() to remove the Prefix and a SUBSTRING() to remove the suffix, but I'm having a hard time applying both. The returned text can be variable length.
I'm trying to avoid declaring a variable, but am open to it. I'd prefer to only use SUBSTRING(), REVERSE(), and CHARINDEX() if possible.
This is what I have so far:
SELECT [Col1]
,SUBSTRING((Col1),CHARINDEX('.', (Col1)) + 1, 999) AS [StrippedPrefix]
,REVERSE(SUBSTRING(REVERSE(Col1),CHARINDEX('-', REVERSE(Col1)) + 1, 999)) AS [StrippedSuffix]
--new SUBSTRING() with both Prefix and Suffix stripped
FROM [Table1]
Declare #YourTable table (Col1 varchar(50))
Insert Into #YourTable values
('Prefix1.ABC-123-Suffix1')
Select *
,String=Substring(Col1,charindex('.',Col1)+1,len(Col1)-charindex('.',Col1)-charindex('-',reverse(Col1)))
From #YourTable
Returns
Col1 String
Prefix1.ABC-123-Suffix1 ABC-123
As per M Ali's suggestion (Even better)
Select *
,String=PARSENAME(REPLACE(Col1 , '-', '.') , 3) + '-' + PARSENAME(REPLACE(Col1 , '-', '.') , 2)
From #YourTable
Here the varaiable is only used as demo - should work with your table as well:
DECLARE #s nvarchar(100) = 'Prefix1.ABC-123-Suffix1'
SELECT #s,
SUBSTRING(#s, 1, CHARINDEX('.', #s)-1) StrippedPrefix,
SUBSTRING(#s, LEN(#s)-CHARINDEX('-', REVERSE(#s))+2, CHARINDEX('-', REVERSE(#s))) StrippedSuffix,
SUBSTRING(#s, CHARINDEX('.', #s)+1, LEN(#s)-CHARINDEX('.', #s)-CHARINDEX('-', REVERSE(#s))) NewString
Here is one way
DECLARE #str VARCHAR(100)= 'Prefix1.ABC-123-Suffix'
SELECT Reverse(Stuff(intr_str, 1, Charindex('-', intr_str), ''))
FROM (SELECT Reverse(Stuff(#str, 1, Charindex('.', #str), '')) AS intr_str) a
Result : ABC-123

How to use substring in SQL Server

Suppose I have this query.
SELECT
proj.refno [Reference No.],
proj.projname [NNNN],
TotalCost= '$' + CONVERT(NVARCHAR(100),cast(ROUND((cast(ship.volfinish as int) * data.price)/1000,2) as decimal(5,2)))
FROM
projects proj
INNER JOIN
projdata data ON proj.controlno = data.controlno
INNER JOIN
shipment ship ON data.ctrlno = ship.dctrlno
WHERE
proj.refno IN ('item1', 'item2','item3')
ORDER BY
proj.refno
with this output:
Reference No. NNNN TotalCost
GR-NFS52 abc123 StudentsTitle123 (NNNN: xxxxxxxxxxxxx) $215.45
GR-PFS53 def456 StudentsTitle456 (NNNN: xxxxxxxxxxxxx) $259.55
GR-SSFS43 ghi789 StudentsTitle789 (NNNN: xxxxxxxxxxxxx) $242.35
How can I make the NNNN column used the substring function with this output. Cause I'm not into t-sql.
NNNN
xxxxxxxxxxxxx
xxxxxxxxxxxxx
xxxxxxxxxxxxx
Assuming you have pattern like NNNN: xxxxxxxxxxx) in your strings you can extract this number using some simple manipulation over the string value using charindex and substring:
declare #str nvarchar(max)
select #str = 'Students (NNNN: 9781410314291)'
select substring(#str,
charindex('ISBN:', #str) + 6,
charindex(')', #str, charindex('NNNN:', #str)) - charindex('NNNN:', #str) - 6)
Here we first find position of NNNN: substring, then position of first occurence of closing bracket ) after this substing and taking part of string between these positions - it is exactly number you need.
In your particular case you can use outer apply in select query in order to make it more readable by avoiding multiple copy-pasting the same charindex('NNNN:', proj.projname) expression:
select
proj.refno [Reference No.],
substring(proj.projname,
CALC.pos_from,
charindex(')', proj.projname, CALC.pos_from) - CALC.pos_from - 6) as [NNNN],
....
FROM projects proj
.....
outer apply (select charindex('NNNN:', proj.projname) as pos_from) as CALC
Try this:
DECLARE #str nvarchar(max) = 'Novels for Students, vol. 52 (ISBN: 9781410314291)'
SELECT
REPLACE(STUFF(#str, 1, PATINDEX('% '+REPLICATE('[0-9]', 13) + '%', #str), ''), ')', '')
Result:
9781410314291

Replacing first occurrence of character with one character and the second with another character in SQL

I have a table with a column Name that can contain substring surrounding with quotations ..."substring"...
For each row in this table I need to replace first occurrence of " with « and second one with »
Each row can contain only one quoted substring.
So if I have a record like this 'fgh"abc"sdf' I want to get this 'fgh«abc»sdf'
I can't come up with a solution for this.
First an example of how the syntax works
DECLARE #a varchar(max) = 'fgh"abc"sdf'
SELECT
stuff(stuff(#a, charindex('"', #a),1, '«'),
charindex('"', #a, charindex('"', #a) + 1), 1, '»')
Result:
fgh«abc»sdf
This is the query needed where col is the name of your column:
SELECT
stuff(stuff(col, charindex('"', col),1, '«'),
charindex('"', col, charindex('"', col) + 1), 1, '»')
FROM yourtable
You can do something like :
DECLARE #TmpVar VARCHAR(100)
SET #TmpVar = 'haha"substring"hehe'
SET #TmpVar = STUFF(#TmpVar, CHARINDEX('"', #TmpVar), 1, '«')
SET #TmpVar = REPLACE(#TmpVar, '"', '»')