Regex in sql server to match numeric data - sql-server

I have a table which looks like
name 34
name 4
name 9
n1am3e jyhjgyn 797907
n1am3e 0yhjgyn 797907
Now i want the output to be like
name
name
name
n1am3e jyhjgyn
n1am3e 0yhjgyn
That is if the last word is only numeric then remove it
select dad, PATINDEX('% [0-9]%',dad) from (select (name) as dad from name) as c
I tried the above code to get the index but in the last case it gives 7 instead of 15

Try this:
CREATE TABLE temp(
name VARCHAR(200)
)
INSERT INTO temp VALUES
('name 34'), ('name 4'), ('name 9'), ('n1am3e jyhjgyn 797907'), ('n1am3e 0yhjgyn 7212'), ('n1am3e 0yhjgyn 72e12'), ('11');
SELECT
CASE
WHEN CHARINDEX(' ', name) > 1 THEN
CASE
WHEN RIGHT(name, CHARINDEX(' ', REVERSE(name)) -1) NOT LIKE '%[^0-9]%' -- check if last word is all digits
THEN LEFT(name, LEN(name) - CHARINDEX(' ', REVERSE(name)))
ELSE name
END
ELSE name
END
FROM temp
DROP TABLE temp

You can write a query as:
SELECT
CASE ISNUMERIC (RIGHT(name, NULLIF(charindex(' ', REVERSE(name)),0)))-- get last word
WHEN 1 THEN -- get string without last word
REVERSE(RIGHT(REVERSE (name), len(name) - NULLIF(charindex(' ', REVERSE(name)),0)))
ELSE name -- get whole string
end
AS dad
FROM #tbl

Try this .. Use string FunctionsLeft,Reverse and Substring
CREATE TABLE #test(name VARCHAR(50))
INSERT #test
VALUES ('name 34'),('name 4'),('name 9'),
('n1am3e jyhjgyn 797907'),
('n1am3e 0yhjgyn 797907')
SELECT CASE
WHEN Patindex('%[a-z]%', LEFT(Reverse(name), CASE
WHEN Charindex(' ', Reverse(name)) = 0 THEN Len(name)
ELSE Charindex(' ', Reverse(name))
END)) = 0 THEN Reverse(Substring(Reverse(name), Charindex(' ', Reverse(name)), Len(name)))
ELSE name
END
FROM #test

Related

SQL Server : how to split fullname into first and last name and show only first 100 characters for last name

Below is the select statement. I'm trying to split the [Display name] column into Firstname and Lastname. But when I try to insert the data into the destination table, I get an error
Data Truncation error
The problem is with the Lastname column in the destination table, it only stores 50 characters. I need to only insert first 20 characters of the last name.
SELECT
SUBSTRING(DisplayName, 1, CHARINDEX(' ', DisplayName) - 1) AS [FirstName],
SUBSTRING(DisplayName, CHARINDEX(' ', DisplayName) + 1, LEN(DisplayName)) AS [LastName]
FROM
[Destination_Table]
WHERE
VoidFlag = 0
AND ControlPlanCode = #ControlPlan
This is the result from the above select :
FirstName LastName
-------------------------------------------
Lynn Trepanier
Becky Simonds
Mary Bell
Lynn Trepanier
Enrollment Services Enrollment Services
Wendy Ferenc
Patrick McGrath
Kevin Weishaar
Benefit Configuration Service Benefit Configuration Service
Try this
SELECT
SUBSTRING(DisplayName, 1, CHARINDEX(' ', DisplayName) - 1) AS [FirstName],
case when LEN(DisplayName) -CHARINDEX(' ', DisplayName) <= 50 then
SUBSTRING(DisplayName, CHARINDEX(' ', DisplayName) + 1, LEN(DisplayName) -CHARINDEX(' ', DisplayName) )
else
SUBSTRING(DisplayName, CHARINDEX(' ', DisplayName) + 1,50 )
end
AS [LastName]
FROM
[Destination_Table]
First, cut the text to the correct length (LEN(DisplayName) -CHARINDEX(' ', DisplayName) )
Secondly, test the length of the truncated text. If it is greater than 50, only cut out 50 characters

How to select a variable length string from between two known strings in SQL Server in a VARCHAR(MAX) where some columns don't have applicable strings

Using SQL Server 2012, I need to get from this example
ColumnName
--------------------------------
Enroll to: Carol Goals are many and varied
characters that don't include desired results
Enroll to: Jan Levinson Goals will be discussed at first encounter
Enroll to: Stephon-Anderson Goals none
NULL
Enroll to: David Goals --Note uneven spaces, Need David
to extract the column to look like:
Name
-----------
Carol
NULL
Jan Levinson
Stephon-Anderson
NULL
David
This code got me pretty close to the results I was looking for, but sometimes trimmed the name incorrectly.
Select
CASE WHEN AssignedTo like '%Enroll To:%' THEN SUBSTRING(AssignedTo, CHARINDEX('%Enroll To:%', AssignedTo) + LEN('%Enroll To:%')
,CHARINDEX('Goals', AssignedTo) - CHARINDEX('%Enroll To:%', AssignedTo) + LEN('Goals'))
ELSE 'None'
END AS 'Name'
FROM
(
Select
CASE WHEN ColumnName like '%Enroll To:%' THEN SUBSTRING (ColumnName, CHARINDEX('Enroll To:', ColumnName), 40)
ELSE 'None'
END AS 'AssignedTo'
FROM TABLE ) A
I cannot thank you enough!
This produced the desired result and seems to deal with variable length of the target string. Hope it helps someone.
DECLARE #pretext as NVARCHAR(100) = 'Enroll to:'
DECLARE #posttext as NVARCHAR(100) = 'Goals'
Select
,CASE When CHARINDEX(#posttext, ColumnName) - (CHARINDEX(#pretext, ColumnName) + len(#pretext)) < 0 THEN NULL
Else
SUBSTRING(ColumnName, CHARINDEX(#pretext, ColumnName) + len(#pretext)
,CHARINDEX(#posttext, ColumnName) - (CHARINDEX(#pretext, ColumnName) + len(#pretext)) )
END as betweentext
FROM TABLE
You can use apply and string functions:
select left(v.s1, charindex(' ', s1) - 1)
from t cross apply
(values (stuff(t.col, 1, 11, '')) v(s1)
Here is an alternative to Gordon's answer:
SELECT
SUBSTRING(ColumnName,
CHARINDEX(':', ColumnName) + 2,
CHARINDEX(' ', ColumnName, CHARINDEX(':', ColumnName) + 2) -
CHARINDEX(':', ColumnName) - 2) AS Name
FROM yourTable;
Demo
Here is your data to test for in table form:
declare #goals table (string nvarchar(255));
insert #goals values
('Enroll to: Carol Goals are many and varied characters that don''t include desired results'),
('Enroll to: Jan Levinson Goals will be discussed at first encounter'),
('Enroll to: Stephon-Anderson Goals none'),
(NULL),
('Enroll to: David Goals '), --Note uneven spaces, Need David
(' '); -- I (psw) added this
And the following code seems to do what you desire without error. But it is assuming that your sentence after the name will always start with "Goals".
select *,
result =
case
when isValid = 1 then
ltrim(rtrim(
substring(string, colonPos + 1, goalsPos - colonPos - 1)
))
end
from #goals
cross apply (select
colonPos = charindex(':', string),
goalsPos = patIndex('%goals%', string)
) positions
cross apply (select
isValid =
case
when colonPos = 0 or goalsPos = 0 or colonPos > goalsPos then 0
else 1
end
) validity

TSQL - Move any text after CR/LF to a new column

We have an address field in our database that I need to split up into two columns (Address1 and Address2). I'm looking for a way to split up this string after the CR/LF section.
How can I do this? I'm using SSMS 2016
Something like this could be used -
Carriage return is char(13)
DECLARE #Str table (str VARCHAR(100))
insert into #Str values
('Test
Word'),
('NoCRLF')
SELECT CASE WHEN CHARINDEX(CHAR(13), Str ) > 0 THEN SUBSTRING(Str , 1, CHARINDEX(CHAR(13), Str ) - 1) ELSE Str END AS [First],
CASE WHEN CHARINDEX(CHAR(13), Str ) > 0 THEN SUBSTRING(Str , CHARINDEX(CHAR(13), Str ) + 1, LEN(Str )) ELSE NULL END AS [Last]
FROM #Str
You can use CHARINDEX to find if your address has new line character or not. and based on that you can split up you address using SUBSTRING.
For address1, you should start from position 1 and end at position 1 less than index of new line character.
Similarly for address2, you should start from position 1 more than index of new line character and end the end of the string.
Code below handles cases like when there is no CHAR(13) you will get Address1 only and Address2 will be NULL. Same way if Address is NULL or Blank space it will handle it.
Below is the sample code:
DECLARE #AddressTable AS TABLE
(
Address nvarchar(MAX) NULL,
Address1 nvarchar(MAX) NULL,
Address2 nvarchar(MAX) NULL
)
INSERT #AddressTable (Address)
SELECT '1600 Pennsylvania Avenue' + CHAR(13) + 'Washington DC ' Address UNION ALL
SELECT '221 B Baker St, London, England' Address UNION ALL
SELECT NULL Address UNION ALL
SELECT '' Address UNION ALL
SELECT '11 Wall Street' + CHAR(13) + 'New York, NY' Address
SELECT
CASE
WHEN CHARINDEX(CHAR(13), Address) > 0 THEN SUBSTRING(Address, 1, CHARINDEX(CHAR(13), Address) - 1) + '|'
ELSE Address END
Address1,
CASE
WHEN CHARINDEX(CHAR(13), Address) > 0 THEN SUBSTRING(Address, CHARINDEX(CHAR(13), Address) + 1, LEN(Address)) + '|'
ELSE NULL END
Address2
FROM #AddressTable
From SQL Server 2016 there is a string_split function:
https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql

split alpha and numeric using sql

I have a table and it has a 3 columns. The first column is the data that contains value(numeric) and unit(percentage and etc..), the second column is numeric column, the third is Unit column. What I want to do is split the numeric and the unit from the first column then put those split-ted data to its designated column.
Here is my table:
I tried this function:SO link here..., it really does splitting alpha and numeric but then I'm new in using SQL Function, my problem there is the parameter must be in string STRING, so what I did is change it to Sub Query but it gives me error.
Sample COde:
SQL FUNCTION:
create function [dbo].[GetNumbersFromText](#String varchar(2000))
returns table as return
(
with C as
(
select cast(substring(S.Value, S1.Pos, S2.L) as int) as Number,
stuff(s.Value, 1, S1.Pos + S2.L, '') as Value
from (select #String+' ') as S(Value)
cross apply (select patindex('%[0-9]%', S.Value)) as S1(Pos)
cross apply (select patindex('%[^0-9]%', stuff(S.Value, 1, S1.Pos, ''))) as S2(L)
union all
select cast(substring(S.Value, S1.Pos, S2.L) as int),
stuff(S.Value, 1, S1.Pos + S2.L, '')
from C as S
cross apply (select patindex('%[0-9]%', S.Value)) as S1(Pos)
cross apply (select patindex('%[^0-9]%', stuff(S.Value, 1, S1.Pos, ''))) as S2(L)
where patindex('%[0-9]%', S.Value) > 0
)
select Number
from C
)
SELECT STATEMENT with SUB Query:
declare #S varchar(max)
select number from GetNumbersFromText(Select SomeColm From Table_Name) option (maxrecursion 0)
BTW, im using sql server 2005.
Thanks!
If the numeric part is always at the beginning, then you can use this:
PATINDEX('%[0-9][^0-9]%', ConcUnit)
to get the index of the last digit.
Thus, this:
DECLARE #str VARCHAR(MAX) = '4000 ug/ML'
SELECT LEFT(#str, PATINDEX('%[0-9][^0-9]%', #str )) AS Number,
LTRIM(RIGHT(#str, LEN(#str) - PATINDEX('%[0-9][^0-9]%', #str ))) As Unit
gives you:
Number Unit
-------------
4000 ug/ML
EDIT:
If numeric data include double values as well, then you can use this:
SELECT LEN(#str) - PATINDEX ('%[^0-9][0-9]%', REVERSE(#str))
to get the index of the last digit.
Thus, this:
SELECT LEFT(#str, LEN(#str) - PATINDEX ('%[^0-9][0-9]%', REVERSE(#str)))
gives you the numeric part.
And this:
SELECT LEFT(#str, LEN(#str) - PATINDEX ('%[^0-9][0-9]%', REVERSE(#str))) AS Numeric,
CASE
WHEN CHARINDEX ('%', #str) <> 0 THEN LTRIM(RIGHT(#str, LEN(#str) - CHARINDEX ('%', #str)))
ELSE LTRIM(RIGHT(#str, PATINDEX ('%[^0-9][0-9]%', REVERSE(#str))))
END AS Unit
gives you both numberic and unit part.
Here are some tests that I made with the data you have posted:
Input:
DECLARE #str VARCHAR(MAX) = '50 000ug/ML'
Output:
Numeric Unit
------------
50 000 ug/ML
Input:
DECLARE #str VARCHAR(MAX) = '99.5%'
Output:
Numeric Unit
------------
99.5
Input:
DECLARE #str VARCHAR(MAX) = '4000 . 35 % ug/ML'
Output:
Numeric Unit
------------------
4000 . 35 ug/ML
Here is my answer. Check output in SQLFiddle for the same.
create TABLE temp
(
string NVARCHAR(50)
)
INSERT INTO temp (string)
VALUES
('4000 ug\ml'),
('2000 ug\ml'),
('%'),
('ug\ml')
SELECT subsrtunit,LEFT(subsrtnumeric, PATINDEX('%[^0-9]%', subsrtnumeric+'t') - 1)
FROM (
SELECT subsrtunit = SUBSTRING(string, posofchar, LEN(string)),
subsrtnumeric = SUBSTRING(string, posofnumber, LEN(string))
FROM (
SELECT string, posofchar = PATINDEX('%[^0-9]%', string),
posofnumber = PATINDEX('%[0-9]%', string)
FROM temp
) d
) t
Updated Version to handle 99.5 ug\ml
create TABLE temp
(
string NVARCHAR(50)
)
INSERT INTO temp (string)
VALUES
('4000 ug\ml'),
('2000 ug\ml'),
('%'),
('ug\ml'),
('99.5 ug\ml')
SELECT subsrtunit,LEFT(subsrtnumeric, PATINDEX('%[^0-9.]%', subsrtnumeric+'t') - 1)
FROM (
SELECT subsrtunit = SUBSTRING(string, posofchar, LEN(string)),
subsrtnumeric = SUBSTRING(string, posofnumber, LEN(string))
FROM (
SELECT string, posofchar = PATINDEX('%[^0-9.]%', string),
posofnumber = PATINDEX('%[0-9.]%', string)
FROM temp
) d
) t
Updated Version: To handle 1 000 ug\ml,20 000ug\ml
create TABLE temp
(
string NVARCHAR(50)
)
INSERT INTO temp (string)
VALUES
('4000 ug\ml'),
('2000 ug\ml'),
('%'),
('ug\ml'),
('99.5 ug\ml'),
('1 000 ug\ml'),
('20 000ug\ml')
SELECT substring(replace(subsrtunit,' ',''),PATINDEX('%[0-9.]%', replace(subsrtunit,' ',''))+1,len(subsrtunit)),
LEFT(replace(subsrtnumeric,' ',''), PATINDEX('%[^0-9.]%', replace(subsrtnumeric,' ','')+'t') - 1)
FROM (
SELECT subsrtunit = SUBSTRING(string, posofchar, LEN(string)),
subsrtnumeric = SUBSTRING(string, posofnumber, LEN(string))
FROM (
SELECT string, posofchar = PATINDEX('%[^0-9.]%', replace(string,' ','')),
posofnumber = PATINDEX('%[0-9.]%', replace(string,' ',''))
FROM temp
) d
) t
Check out SQLFiddle for the same.
Would something like this work? Based on the shown data it looks like it would.
Apply it to your data set as a select and if you like the results then you can make an update from it.
WITH cte as (SELECT 'ug/mL' ConcUnit, 500 as [Numeric], '' as Unit
UNION ALL SELECT '2000 ug/mL', NULL, '')
SELECT
[ConcUnit] as [ConcUnit],
[Numeric] as [Original Numeric],
[Unit] as [Original Unit],
CASE WHEN ConcUnit LIKE '% %' THEN
SUBSTRING(ConcUnit, 1, CHARINDEX(' ', ConcUnit) - 1)
ELSE [Numeric] END as [New Numeric],
CASE WHEN ConcUnit LIKE '% %'
THEN SUBSTRING(ConcUnit, CHARINDEX(' ', ConcUnit) + 1, LEN(ConcUnit))
ELSE ConcUnit END as [New Unit]
FROM cte
change #concunit & #unitx Respectively
DECLARE #concunit varchar(10)='45.5%'
DECLARE #unitx varchar(10)='%'
BEGIN
SELECT RTRIM(SUBSTRING( #concunit , 1 , CHARINDEX( #unitx , #concunit
) - 1
)) AS Number,
RTRIM(SUBSTRING( #concunit , CHARINDEX( #unitx , #concunit
) , LEN( #concunit
) - (CHARINDEX( #unitx , #concunit
) - 1)
)) AS Unit
end
I had the same dilemma, but in my case the alpha's were in front of the numerics.
So using the logic that #Giorgos Betsos added to his answer, I just reversed it.
I.e., when your input is :
abc123
You can split it like this:
declare #input varchar(30) = 'abc123'
select
replace(#input,reverse(LEFT(reverse(#input), PATINDEX('%[0-9][^0-9]%', reverse(#input) ))),'') Alpha
, reverse(LEFT(reverse(#input), PATINDEX('%[0-9][^0-9]%', reverse(#input) ))) Numeric
Results :

How to switch data in a column and update the column with result information in SQL Server

I have a table USERS and it has a column FULLNAME that contains full users names in the format FirstName LastName and I need to switch the data, and update it in the same column, using this format LastName, FirstName.
Ex. James Brown needs to be switched to Brown, James and updated in the same column (FULLNAME)
Is there any way to do it?
Thanks.
The best solution would be to split the elements into two columns (LastName, FirstName). However, if you want to try and squeeze it into 1 column, and you're assuming that every name is split by a single space
DECLARE #Users TABLE ( Name VARCHAR(100) )
INSERT INTO #Users
( Name
)
SELECT 'James Brown'
UNION ALL
SELECT 'Mary Ann Watson'
SELECT RIGHT(Name, CHARINDEX(' ', REVERSE(Name)) - 1) + ', ' + LEFT(Name,
LEN(Name)
- CHARINDEX(' ',
REVERSE(Name)))
FROM #Users
This also assumes that if they have more than two names sperated by a space, then the last word is the last name, and everything else is first name. Works for "Mary Ann Watson", but not "George Tucker Jones", if "Tucker Jones" is a last name.
Assuming they only have 1 space in the name:
UPDATE USERS
SET FULLNAME = RIGHT(FULLNAME,len(FULLNAME) - CHARINDEX(' ',FULLNAME)) +', '+ LEFT(FULLNAME,charindex(' ',FULLNAME)-1)
WHERE LEN(FULLNAME) - LEN(REPLACE(FULLNAME, ' ', '')) = 1

Resources