SQL split based on delimeter, keep only second element - sql-server

I have T-SQL code and am researching how to split
Aruba\abc
Spain\defg
New Zealand\qwerty
Antartica\sporty
Such that the column outputs
abc
defg
qwerty
sporty
So far, I found something like this,
http://www.aspsnippets.com/Articles/Split-function-in-SQL-Server-Example-Function-to-Split-Comma-separated-Delimited-string-in-SQL-Server-2005-2008-and-2012.aspx
But it splits column based on delimiters into new columns.
I wish to keep the information AFTER the delimiter \
Please advise

SELECT RIGHT(ColName , LEN(ColName) - CHARINDEX('\', ColName) )
FROM TABLEName
OR
SELECT PARSENAME(REPLACE(ColName , '\' , '.'),1)
FROM TableName

If you have it as a variable example:
DECLARE #str VARCHAR(50) = 'aruba\abc'
SELECT SUBSTRING(#str,CHARINDEX('\', #str)+1, LEN(#str) - CHARINDEX('\', #str) )
If you have it in a table example:
SELECT SUBSTRING(column1,CHARINDEX('\', column1)+1, LEN(column1) - CHARINDEX('\', column1) )
FROM table1
Here's a sqlfiddle of it working : http://sqlfiddle.com/#!6/85de5/1

Related

How does declaring and using a variable in TSQL select statement give a different result

I want to get a list of comma separated customer names. The below code only returns the last name
DECLARE #vfirstname NVARCHAR(500), #vdelimiter NVARCHAR(1)
SET #vdelimiter=','
SELECT #vfirstname = FirstName + #vdelimiter
FROM dbo.Customer c
SET #vfirstname = LEFT(#vfirstname, LEN( #vfirstname ) - 1);
PRINT #vfirstname
I was able to fix it introducing the below statements (with help from google):
SET #vfirstname =''
SELECT #vfirstname = #vfirstname + FirstName + #vdelimiter
FROM dbo.Customer c
But I am unable to understand the need to do this , how does the select statement really work in this scenario?
This will do what you need without the substring function, the
Select ',' is your delimiter
The stuff function removes the first comma/delimiter from the list for you using the XML path
-- use stuff instead of substringb
Select STUFF((
SELECT ',' + FirstName
FROM dbo.Customer
FOR XML PATH('')
), 1, 1,'')
FROM dbo.Customer
-- if you want a space after comma, need to update the STUFF to be 1, 2

SQL String: Counting Words inside a String

I searched through many of the questions here but all I found with decent answer is for different language like Javascript etc.
I have a simple task in SQL that I can't seem to find a simple way to do.
I just need to count the number of "words" inside a SQL string (a sentence). You can see why "words" is in quotes in my examples. The "words" are delimited by white space.
Sample sentences:
1. I am not your father.
2. Where are your brother,sister,mother?
3. Where are your brother, sister and mother?
4. Who are you?
Desired answer:
1. 5
2. 4
3. 7
4. 3
As you can see, I need to count the "words" disregarding the symbols (I have to treat them as part of the word). So in sample no. 2:
(1)Where (2)are (3)your (4)brother,sister,mother? = 4
I can handle the multiple whitespaces by doing a replace like this:
REPLACE(string, ' ', ' ') -> 2 whitespaces to 1
REPLACE(string, ' ', ' ') -> 3 whitespaces to 1 and so on..
What SQL function can I use to do this? I use SQL Server 2012 but needs a function that works in SQL Server 2008 as well.
Here is one way to do it:
Create and populate sample table (Please save is this step in your future questions)
DECLARE #T AS TABLE
(
id int identity(1,1),
string varchar(100)
)
INSERT INTO #T VALUES
('I am not your father.'),
('Where are your brother,sister,mother?'),
('Where are your brother, sister and mother?'),
('Who are you?')
Use a cte to replace multiple spaces to a single space (Thanks to Gordon Linoff's answer here)
;WITH CTE AS
(
SELECT Id,
REPLACE(REPLACE(REPLACE(string, ' ', '><' -- Note that there are 2 spaces here
), '<>', ''
), '><', ' '
) as string
FROM #T
)
Query the CTE - length of the string - length of the string without spaces + 1:
SELECT id, LEN(string) - LEN(REPLACE(string, ' ', '')) + 1 as CountWords
FROM CTE
Results:
id CountWords
1 5
2 4
3 7
4 3
This is a minor improvement of #ZoharPeled's answer. This can also handle 0 length values:
DECLARE #t AS TABLE(id int identity(1,1), string varchar(100))
INSERT INTO #t VALUES
('I am not your father.'),
('Where are your brother,sister,mother?'),
('Where are your brother, sister and mother?'),
('Who are you?'),
('')
;WITH CTE AS
(
SELECT
Id,
REPLACE(REPLACE(string,' ', '><'), '<>', '') string
FROM #t
)
SELECT
id,
LEN(' '+string)-LEN(REPLACE(string, '><', ' ')) CountWords
FROM CTE
To handle multiple spaces too, use the method shown here
Declare #s varchar(100)
set #s='Who are you?'
set #s=ltrim(rtrim(#s))
while charindex(' ',#s)>0
Begin
set #s=replace(#s,' ',' ')
end
select len(#s)-len(replace(#s,' ',''))+1 as word_count
https://exploresql.com/2018/07/31/how-to-count-number-of-words-in-a-sentence/
I found this query more useful than the first. it omit extra characters and numbers and symbols, so it would count just words within a passage...
drop table if exists #t
create table #t (id int identity(1,1), c1 varchar(2000))
insert into #t (c1)
values
('Alireza Sattarzadeh Farkoush '),
('yes it is the   best .'),
('abc def ghja a the . asw'),
('?>< 123 ...!  z a b'),
('Wallex is   the greatest exchange in the .. world a after binance ...!')
select c1 , Count(*)
from (
select id, c1, value  
from #t t
cross apply (
select rtrim(ltrim(value)) as value from string_split(c1,' ')) a
where len(value) > 1 and value like '%[a-Z]%'
) Final
group by c1

Remove specific characters from column

I would like to remove specific characters from a column using regexp.
As an example, I have this:
declare #a nvarchar(50) = '(djfhsd-kjfhksd'
select Replace(#a, Substring(#a, PatIndex('%[^0-9.-]%', #a), 1), '')
But I want to remove just parenthesis (), spaces and dashes -
I don't have experience on regexp but I would like to remove them in one shot.
declare #a nvarchar(50) = '(djfhsd-kjfhksd'
Select #a =Replace(#a,RemChar,'')
From (Values ('('),
(')'),
('-'),
(' ')
) B (RemChar)
Select #a
Returns
djfhsdkjfhksd
For something straight forward. Otherwise you will need a UDF or a Cross Apply
Replace(Replace(Replace(Replace(YourCol,'(',''),')',''),'-',''),' ','')

SQL Server : select all after specific character

How I can select
"ALT1" if value is "W61N03D20V0-WHIH-ALT1"
"ALT2" if for "W61N03D20V0-WHIH-ALT2"
"SW" for "W61N03D20V0-WHIH-SW"
"Default" for "W61N26D1YA1-VICU" (without prefix)
"Defailt" for "W61N27D21V2-AZTD"
In other words I'm looking for a way extract last part after second suffix, but if I have't second suffix - then default
Thanks for advice
Try it like this:
First you "split" the string on its minus signs with the XML trick.
Then you read the third node from you XML - voila!
CREATE TABLE #tbl(content VARCHAR(100));
INSERT INTO #tbl VALUES('W61N03D20V0-WHIH-ALT1')
,('W61N03D20V0-WHIH-SW')
,('W61N26D1YA1-VICU');
WITH SplittedAsXml AS
(
SELECT CAST('<x>' + REPLACE(content,'-','</x><x>') + '</x>' AS XML) AS Content
FROM #tbl
)
SELECT ISNULL(Content.value('/x[3]','varchar(max)'),'default') AS TheThirdPart
FROM SplittedAsXml;
DROP TABLE #tbl;
The result
ALT1
SW
default
Going this ways would also give you the chance to get the other parts in one go just querying /x[1] and /x[2] too
I did it using the built-in substring() function:
declare #str VARCHAR(40) = 'W61N03D20V0-WHIH-ALT1' -- also works for the other examples
declare #sep VARCHAR(1) = '-'
declare #middleToEnd VARCHAR(40) = substring(#str, charindex(#sep, #str) + 1, len(#str))
declare #pos INT = charindex(#sep, #middleToEnd)
declare #lastPart VARCHAR(40) =
CASE WHEN #pos = 0
THEN 'Default'
ELSE substring(#middleToEnd, #pos + 1, len(#middleToEnd))
END
select #lastPart
For best performance, you can solve it with this one-liner(calculation is one line)
SELECT
COALESCE(STUFF(col,1,NULLIF(CHARINDEX('-',col, CHARINDEX('-',col)+1), 0),''),'Default')
FROM (values
('W61N03D20V0-WHIH-ALT1'),('W61N03D20V0-WHIH-ALT2'),
('W61N03D20V0-WHIH-SW'),('W61N26D1YA1-VICU'),
('W61N27D21V2-AZTD')) x(col)
Result:
ALT1
ALT2
SW
Default
Default
If I understand what you are asking for, the following does what you need:
-- fake table
WITH SomeTable AS (
SELECT 'W61N03D20V0-WHIH-ALT1' AS Field1
UNION ALL
SELECT 'W61N03D20V0-WHIH-SW'
UNION ALL
SELECT 'W61N26D1YA1-VICU'
)
-- select
SELECT
CASE CHARINDEX('-WHIH-', Field1)
WHEN 0 THEN 'Default'
ELSE SUBSTRING(Field1, CHARINDEX('-WHIH-', Field1) + 6, LEN(Field1) - (CHARINDEX('-WHIH-', Field1) + 5))
END
FROM SomeTable
Use can use a CASE expression to check whether the string starts with W61N03D20V0-WHIH.
If it starts with it use a combination of RIGHT, REVERSE and CHARINDEX functions to get last part from the string, else Default.
Query
select case when [your_column_name] like 'W61N03D20V0-WHIH%'
then right([your_column_name], charindex('-', reverse([your_column_name]), 1) - 1)
else 'Default' end as new_column_name
from your_table_name;
SQl Fiddle demo

How do I parse through a string that is dynamic?

How can I parse through dynamic strings to pull out data? Example Below: (Written in T-SQL for SQL Server 2008 R2)
The Date to parse through:
BUSINESS=12^REFERENCE=9255^ACCOUNT_TYPE=SUPPLIER^SHIPPING_ID=ACHP^
I need the REFERENCE number when the ACCOUNT_TYPE=SUPPLIER.
The Reference Number can be from 1 to 16 characters in length.
My SQL-statement would look something like this:
SELECT <REFERENCE NUMBER> FROM ACCOUNTS
The result would look something like this:
9255
84
1
151221
415
99
etc...
You should normalize your data. But here is a solution.
declare #accounts table(col1 varchar(max))
insert #accounts values('BUSINESS=12^REFERENCE=9255^ACCOUNT_TYPE=SUPPLIER^SHIPPING_ID=ACHP^')
SELECT replace(data, 'REFERENCE=', '') FROM
(
SELECT t.c.value('.', 'VARCHAR(2000)') data
FROM (
SELECT x = CAST('<t>' +
REPLACE(col1, '^', '</t><t>') + '</t>' AS XML)
FROM #accounts
WHERE col1 like '%ACCOUNT_TYPE=SUPPLIER%'
) a
CROSS APPLY x.nodes('/t') t(c)
) x
WHERE data like 'REFERENCE=%'
Result:
9255
Fix your data, that will save you from alot of grief
This will give you the number you are looking for from each row containing the example you gave:
DECLARE #text VARCHAR(50)
SET #text = 'BUSINESS=12^REFERENCE=9255^ACCOUNT_TYPE=SUPPLIER^SHIPPING_ID=ACHP^'
SELECT SUBSTRING(#text,CHARINDEX('^REFERENCE',#text)+11,
(CHARINDEX('^ACCOUNT_TYPE',#text))
- (CHARINDEX('^REFERENCE',#text)+11))
Just replace the #text with the field name and your are good to go!

Resources