Related
For ex : if sql column value is sa,123k and the output should first three characters i.e. sak
Letters and any special characters needs to be eliminated and gets only three characters. How do we do this ?
You can use recursive CTEs for this purpose:
with t as (
select 'sa,123k' as str
),
cte as (
select str, left(str, 1) as c, stuff(str, 1, 1, '') as rest, 1 as lev,
convert(varchar(max), (case when left(str, 1) like '[a-zA-Z]' then left(str, 1) else '' end)) as chars
from t
union all
select str, left(rest, 1) as c, stuff(rest, 1, 1, '') as rest, lev + 1,
convert(varchar(max), (case when left(rest, 1) like '[a-zA-Z]' then chars + left(rest, 1) else chars end))
from cte
where rest > '' and len(chars) < 3
)
select str, max(chars)
from cte
where len(chars) <= 3
group by str;
Here is a db<>fiddle.
This might help
DECLARE #VAR VARCHAR(100)= 'sa,1235JSKL', #RESULT VARCHAR(MAX)=''
SELECT #RESULT = #RESULT+
CASE WHEN RESULT LIKE '[a-zA-Z]' THEN RESULT ELSE '' END
FROM (
SELECT NUMBER, SUBSTRING(#VAR,NUMBER,1) AS RESULT
FROM MASTER..spt_values
WHERE TYPE = 'P' AND NUMBER BETWEEN 1 AND LEN(#VAR)
)A
ORDER BY NUMBER
SELECT SUBSTRING(#RESULT,1,3)
If you want to apply this on a Tables column, you need to create Scalar function with same logic. You can find more number of articles how to create the scalar function by Googling..
You can use this function which is written by G Mastros to do this.
Create Function [dbo].[RemoveNonAlphaCharacters](#Temp nvarchar(MAX))
Returns nvarchar(MAX)
AS
Begin
Declare #KeepValues as nvarchar(MAX)
Set #KeepValues = '%[^a-z]%'
While PatIndex(#KeepValues, #Temp) > 0
Set #Temp = Stuff(#Temp, PatIndex(#KeepValues, #Temp), 1, '')
Return #Temp
End
Then simply call the fuction like this
SELECT LEFT(dbo.RemoveNonAlphaCharacters(colName), 3)
FROM TableName
Reference: G Mastros answer on "How to strip all non-alphabetic characters from string in SQL Server" question.
Well, this is ugly, but you could replace all the characters you don't like.
In your example, this would be:
SELECT REPLACE (REPLACE (REPLACE (REPLACE ('sa,123k', '1', ''), '2', ''), '3', ''), ',', '')
Obviously, this needs a lot of replaces if you need all numbers and other sorts of characters replaced.
Edited, based on your comment:
SELECT REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (REPLACE ('123456gh,.!879k', '1', ''), '2', ''), '3', ''), ',', ''), '4', ''), '5', ''), '6', ''), '.', ''), '!', ''), '7', ''), '8', ''), '9', '')
How Can I separate characters and number from a word using SQL Server query?
Example word: AB12C34DE
The Output is like:
col1
-----
ABCDE
col2
-----
1234
Please try this.
DECLARE #Numstring varchar(100)
SET #Numstring = 'AB12C34DE'
WHILE PATINDEX('%[^0-9]%',#Numstring) <> 0.
SET #Numstring = STUFF(#Numstring,PATINDEX('%[^0-9]%',#Numstring),1,'')
SELECT #Numstring As Number
DECLARE #Charstring varchar(100)
SET #Charstring = 'AB12C34DE'
WHILE PATINDEX('%[^A-Z]%',#Charstring) <> 0.
SET #Charstring = STUFF(#Charstring,PATINDEX('%[^A-Z]%',#Charstring),1,'')
SELECT #Charstring As Character
Try it like this:
DECLARE #word VARCHAR(100)='AB12C34DE';
WITH Tally(Nmbr) AS
(
SELECT TOP(LEN(#word)) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values
)
,Separated AS
(
SELECT CASE WHEN OneChar LIKE '[0-9]' THEN 1 ELSE 0 END AS IsDigit
,OneChar
,Nmbr
FROM Tally
CROSS APPLY(SELECT SUBSTRING(#word,Nmbr,1)) A(OneChar)
)
SELECT (SELECT OneChar AS [*] FROM Separated WHERE IsDigit=1 ORDER BY Nmbr FOR XML PATH(''),TYPE).value('.','nvarchar(max)') AS AllNumbers
,(SELECT OneChar AS [*] FROM Separated WHERE IsDigit=0 ORDER BY Nmbr FOR XML PATH(''),TYPE).value('.','nvarchar(max)') AS AllCharacters;
Some explanation
The idea uses a tally table (a list of numbers). You might use an existing physical numbers table...
The first CTE "Tally" will create a derived list of numbers (1,2,3, ...), one for each character.
The second CTE will read each character one-by-one and mark it as digit or not.
The final query will re-concatenate the list of characters
As you are using SQL Server 2012 so you can't use TRANSLATE which can simplify this.
One ways is to use REPLACE like following. If you want you can convert it to a user defined function so that you don't have to write same thing again and again.
DECLARE #TABLE TABLE(VAL VARCHAR(100))
INSERT INTO #TABLE SELECT 'AB12C34DE'
SELECT REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE (VAL, '0', ''),
'1', ''),
'2', ''),
'3', ''),
'4', ''),
'5', ''),
'6', ''),
'7', ''),
'8', ''),
'9', '') COL1,
REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE (VAL, 'A', ''),
'B', ''),
'C', ''),
'D', ''),
'E', ''),
'F', ''),
'6', ''),
'G', ''),
'H', ''),
'I', '') COL2
--ADD OTHER CHARACTERS
FROM #TABLE
This seems like a good place to use a recursive CTE:
with cte as (
select v.str, convert(varchar(max), '') as digits, convert(varchar(max), '') as chars, 1 as lev
from (values ('AB12C34DE')) v(str)
union all
select stuff(str, 1, 1, ''),
(case when left(str, 1) like '[0-9]' then digits + left(str, 1) else digits end),
(case when left(str, 1) like '[a-zA-Z]' then chars + left(str, 1) else chars end),
lev + 1
from cte
where str > ''
)
select top (1) with ties cte.*
from cte
order by row_number() over (order by lev desc);
As the values() clause suggests, this will work on columns in a table as well as constants.
I am trying to create a new column in my results that is made up on the first 3 characters of "PrimaryName", all of "VendorCity", and the first 5 characters of "VendorZip"
SELECT,VendorName
,replace(PrimaryVendorLocationName,' ','') as PrimaryName
,replace(PrimaryVendorLocationCity,' ','') as VendorCity
,replace(PrimaryVendorLocationZipCode,' ','') as VendorZip
FROM [table]
As you can see I also need to remove spaces to ensure a cleaner return. I would like to call the new column "NewVendorCode". So a record that originates like this:
R A Slack
Chicago Heights
60654-1234
Will return this:
RASChicagoHeights60654
You can use the following, using LEFT (MySQL / TSQL):
SELECT CONCAT(
LEFT(REPLACE(PrimaryVendorLocationName, ' ', ''), 3),
REPLACE(PrimaryVendorLocationCity, ' ', ''),
LEFT(REPLACE(PrimaryVendorLocationZipCode, ' ', ''), 5)
) FROM table_name
... or you can use SUBSTRING (MySQL / TSQL) (instead of LEFT):
SELECT CONCAT(
SUBSTRING(REPLACE(PrimaryVendorLocationName, ' ', ''), 1, 3),
REPLACE(PrimaryVendorLocationCity, ' ', ''),
SUBSTRING(REPLACE(PrimaryVendorLocationZipCode, ' ', ''), 1, 5)
) FROM table_name
Note: As you can see the SELECT querys work on MySQL and TSQL without change.
demo (MySQL): https://www.db-fiddle.com/f/wTuKzosFgkEuKXtruCTCxg/0
demo (TSQL): http://sqlfiddle.com/#!18/dbc98/1/1
You can use the following code:
SELECT VendorName+
replace(PrimaryVendorLocationName,' ','') +
replace(PrimaryVendorLocationCity,' ','') +
replace(PrimaryVendorLocationZipCode,' ','') as NewVendorCode
SELECT VendorName
,PrimaryName
,VendorCity
,VendorZip
,CONCAT(LEFT(PrimaryName,3),VendorCity,LEFT(VendorZip,5)) As NewVendorCode
FROM (
SELECT VendorName
,replace(PrimaryVendorLocationName,' ','') as PrimaryName
,replace(PrimaryVendorLocationCity,' ','') as VendorCity
,replace(PrimaryVendorLocationZipCode,' ','') as VendorZip
FROM [table]
)
I need to take the values from 3 columns and group them into 1 column as comma separated:
2014-01-01,2014-01-29
The problem is that one or more columns can be NULL and therefore it messes up the commas as such:
2014-01-01,,2014-01-29
This is how I have it coded (the case statement basically just strips out a comma if it's the last character in the string.
I need to add some logic so that it takes into account NULLs but I'm having a hard time coming up with it.
CASE WHEN RIGHT(ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate, 1) = ','
THEN LEFT(ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate, LEN(ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate) - 1)
ELSE ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate
END AS AlLGapDatesFormatted
EDIT -
I need to group the highlighted (notice that PayrollGapDate is ''):
And this is what I'm getting:
And this is the code I implemented:
try using this technique:
SET CONCAT_NULL_YIELDS_NULL ON --<<<make sure concatenations with NULL result in NULL
DECLARE #C1 varchar(10)='AAA'
,#C2 varchar(10)='BBB'
,#C3 varchar(10)=null
,#C4 varchar(10)='DDD'
SELECT STUFF( ISNULL(', '+#C1,'')
+ISNULL(', '+#C2,'')
+ISNULL(', '+#C3,'')
+ISNULL(', '+#C4,'')
,1,2,''
)
output:
-----------------------------------------------
AAA, BBB, DDD
(1 row(s) affected)
You let the ', '+#C3 result in NULL, which the ISNULL(***,'') converts to empty string. The STUFF(***,1,2,'') removes the leading comma and space.
try:
SELECT STUFF( ISNULL(', '+d.FirstGapDate,'')
+ISNULL(', '+d.PayrollGapDate,'')
+ISNULL(', '+d.LastGapDate,'')
,1,2,''
)
FROM ...
WHERE...
You can apply something like this above your expression to replace many commas with one comma:
declare #s varchar(100) = 'ABC,,,,DEF'
select replace(replace(replace(#s, ',', '[]'), '][', ''), '[]', ',')
I have a large database in which I want to do a part string search. The user will enter characters: JoeBloggs.
For arguments sake if I had a name Joe 23 Blo Ggs 4 in the database. I want to remove everything in the name other than A-Z.
I have the REPLACE(Name, ' ','') function to remove spaces and the UPPER() function to capitalize the name.
Is there a more efficient fast way maybe by terms of regex to replace anything other than A-Z. I cannot change the values in the database.
1st option -
You can nest REPLACE() functions up to 32 levels deep. It runs fast.
REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE (#str, '0', ''),
'1', ''),
'2', ''),
'3', ''),
'4', ''),
'5', ''),
'6', ''),
'7', ''),
'8', ''),
'9', '')
2nd option --
do the reverse of -
Removing nonnumerical data out of a number + SQL
3rd option - if you want to use regex
then
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=27205
This one works for me
CREATE Function [dbo].[RemoveNumericCharacters](#Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin
Declare #NumRange as varchar(50) = '%[0-9]%'
While PatIndex(#NumRange, #Temp) > 0
Set #Temp = Stuff(#Temp, PatIndex(#NumRange, #Temp), 1, '')
Return #Temp
End
and you can use it like so
SELECT dbo.[RemoveNumericCharacters](Name) FROM TARGET_TABLE
Try below for your query. where val is your string or column name.
CASE WHEN PATINDEX('%[a-z]%', REVERSE(val)) > 1
THEN LEFT(val, LEN(val) - PATINDEX('%[a-z]%', REVERSE(val)) + 1)
ELSE '' END
I just started relearning SQL...and I read this somewhere:
SELECT TRIM('0123456789' FROM customername )
You can also use this to remove spaces or other symbols as well. Just include it in the first parameter within the quotes ''.
One more approach using Recursive CTE..
declare #string varchar(100)
set #string ='te165st1230004616161616'
;With cte
as
(
select #string as string,0 as n
union all
select cast(replace(string,n,'') as varchar(100)),n+1
from cte
where n<9
)
select top 1 string from cte
order by n desc
**Output:**
test
Quoting part of #Jatin answer with some modifications,
use this in your where statement:
SELECT * FROM .... etc.
Where
REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE (Name, '0', ''),
'1', ''),
'2', ''),
'3', ''),
'4', ''),
'5', ''),
'6', ''),
'7', ''),
'8', ''),
'9', '') = P_SEARCH_KEY
DecLARE #input varchar(50)= 'Joe 23 Blo Ggs 4'
SELECT TRANSLATE(#input,'0123456789',' ') As output1,
REPLACE
(
TRANSLATE(#input,'0123456789',' ') /*10 spaces here*/
, ' '
,''
) as output2
Entire SELECT returns string: $P#M from Python. Multiple spaces can be removed using this approach.
SELECT
REPLACE
(
TRANSLATE
(
'$P#M 1244 from93 Python', -- Replace each char from this string
'123456789', -- that is met in this set with
'000000000' -- the corresponding char from this set.
),
'0', -- Now replace all '0'
'' -- with nothing (void) (delete it).
) AS CLEARED;
Remove everything after first digit (was adequate for my use case):
LEFT(field,PATINDEX('%[0-9]%',field+'0')-1)
Remove trailing digits:
LEFT(field,len(field)+1-PATINDEX('%[^0-9]%',reverse('0'+field))
Not tested, but you can do something like this:
Create Function dbo.AlphasOnly(#s as varchar(max)) Returns varchar(max) As
Begin
Declare #Pos int = 1
Declare #Ret varchar(max) = null
If #s Is Not Null
Begin
Set #Ret = ''
While #Pos <= Len(#s)
Begin
If SubString(#s, #Pos, 1) Like '[A-Za-z]'
Begin
Set #Ret = #Ret + SubString(#s, #Pos, 1)
End
Set #Pos = #Pos + 1
End
End
Return #Ret
End
The key is to use this as a computed column and index it. It doesn't really matter how fast you make this function if the database has to execute it against every row in your large table every time you run the query.