How to split a single column values to multiple column values? - sql

I have a problem splitting single column values to multiple column values.
For Example:
Name
------------
abcd efgh
ijk lmn opq
asd j. asdjja
asb (asdfas) asd
asd
and I need the output something like this:
first_name last_name
----------------------------------
abcd efgh
ijk opq
asd asdjja
asb asd
asd null
The middle name can be omitted (no need for a middle name) The columns are already created and need to insert the data from that single Name column.

Your approach won't deal with lot of names correctly but...
SELECT CASE
WHEN name LIKE '% %' THEN LEFT(name, Charindex(' ', name) - 1)
ELSE name
END,
CASE
WHEN name LIKE '% %' THEN RIGHT(name, Charindex(' ', Reverse(name)) - 1)
END
FROM YourTable

An alternative to Martin's
select LEFT(name, CHARINDEX(' ', name + ' ') -1),
STUFF(name, 1, Len(Name) +1- CHARINDEX(' ',Reverse(name)), '')
from somenames
Sample table
create table somenames (Name varchar(100))
insert somenames select 'abcd efgh'
insert somenames select 'ijk lmn opq'
insert somenames select 'asd j. asdjja'
insert somenames select 'asb (asdfas) asd'
insert somenames select 'asd'
insert somenames select ''
insert somenames select null

;WITH Split_Names (Name, xmlname)
AS
(
SELECT
Name,
CONVERT(XML,'<Names><name>'
+ REPLACE(Name,' ', '</name><name>') + '</name></Names>') AS xmlname
FROM somenames
)
SELECT
xmlname.value('/Names[1]/name[1]','varchar(100)') AS first_name,
xmlname.value('/Names[1]/name[2]','varchar(100)') AS last_name
FROM Split_Names
and also check the link below for reference
http://jahaines.blogspot.in/2009/06/converting-delimited-string-of-values.html

What you need is a split user-defined function. With that, the solution looks like
With SplitValues As
(
Select T.Name, Z.Position, Z.Value
, Row_Number() Over ( Partition By T.Name Order By Z.Position ) As Num
From Table As T
Cross Apply dbo.udf_Split( T.Name, ' ' ) As Z
)
Select Name
, FirstName.Value
, Case When ThirdName Is Null Then SecondName Else ThirdName End As LastName
From SplitValues As FirstName
Left Join SplitValues As SecondName
On S2.Name = S1.Name
And S2.Num = 2
Left Join SplitValues As ThirdName
On S2.Name = S1.Name
And S2.Num = 3
Where FirstName.Num = 1
Here's a sample split function:
Create Function [dbo].[udf_Split]
(
#DelimitedList nvarchar(max)
, #Delimiter nvarchar(2) = ','
)
RETURNS TABLE
AS
RETURN
(
With CorrectedList As
(
Select Case When Left(#DelimitedList, Len(#Delimiter)) <> #Delimiter Then #Delimiter Else '' End
+ #DelimitedList
+ Case When Right(#DelimitedList, Len(#Delimiter)) <> #Delimiter Then #Delimiter Else '' End
As List
, Len(#Delimiter) As DelimiterLen
)
, Numbers As
(
Select TOP( Coalesce(DataLength(#DelimitedList)/2,0) ) Row_Number() Over ( Order By c1.object_id ) As Value
From sys.columns As c1
Cross Join sys.columns As c2
)
Select CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
, Substring (
CL.List
, CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen
, CharIndex(#Delimiter, CL.list, N.Value + 1)
- ( CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen )
) As Value
From CorrectedList As CL
Cross Join Numbers As N
Where N.Value <= DataLength(CL.List) / 2
And Substring(CL.List, N.Value, CL.DelimiterLen) = #Delimiter
)

SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(rent, ' ', 1), ' ', -1) AS currency,
SUBSTRING_INDEX(SUBSTRING_INDEX(rent, ' ', 3), ' ', -1) AS rent
FROM tolets

I used it recently:
select
substring(name,1,charindex(' ',name)-1) as Col1,
substring(name,charindex(' ',name)+1,len(name)) as Col2
from TableName

Here is how I did this on a SQLite database:
SELECT SUBSTR(name, 1,INSTR(name, " ")-1) as Firstname,
SUBSTR(name, INSTR(name," ")+1, LENGTH(name)) as Lastname
FROM YourTable;
Hope it helps.

Related

How to get the first letter of each word in SQL

I tried to run this query to get the initial letter of each word, and it worked for strings of 4 words, yet if the string has only two words, it duplicates the second word's initial.
select
substring(column_name, 1, 1) +
case
when 0 <> charindex(' ', column_name) + 1
then substring(column_name, charindex(' ',column_name) + 1, 1)
else ''
end +
case
when 0 <> charindex(' ', column_name, charindex(' ', column_name) + 1)
then substring(column_name, charindex(' ', column_name, charindex(' ', column_name) + 1) + 1, 1)
else ''
end +
case
when 0 <> charindex(' ', column_name, charindex(' ', column_name, charindex(' ', column_name) + 1) + 1)
then substring(column_name, charindex(' ', column_name, charindex(' ', column_name, charindex(' ', column_name) + 1) + 1) + 1, 1)
else ''
end
from table_name
You didn't specify which RDBMS you are using. This should work in SQL Server:
drop table if exists table_name
create table table_name (
column_name varchar(255)
)
insert table_name
values ('See Jane')
, ('See Jane run')
, ('See Jane run and jump over the lazy dog.')
select stuff((SELECT '' + t2.fc
from (
select left(str.value, 1) fc
, charindex(' ' + str.value + ' ', ' ' + t.column_name + ' ') idx
from string_split(t.column_name, ' ') str
) t2
order by t2.idx
FOR XML PATH('')
), 1, 0, '') as FirstChars
from table_name t
The idx column is used to order the ouptut because string_split does not promise to return the results in any particular order. Thanks to Aaron Bertrand - https://dba.stackexchange.com/questions/207274/string-split-and-ordered-results
Given the use of charindex in your question, I'm assuming you are using SQL Server. The CTE generates a tall view of your data using string_split function, with each letter on it's own row. We then select from it and group by id, and apply the string_agg function to place back into a single row.
Password guessing?
create table my_data (
id integer,
comments varchar(50)
);
insert into my_data (id, comments) values
(1, 'Thank goodness its friday'),
(2, 'I want 2 scoops of ice cream');
select * from my_data;
id
comments
1
Thank goodness its friday
2
I want 2 scoops of ice cream
with cte (id, first_char) as (
select id, substring(ss.value, 1, 1) as first_char
from my_data
cross apply string_split(comments, ' ')ss
)
select t.id,
string_agg(t.first_char, ',') as letters_delimited,
string_agg(t.first_char, '') as letters_not_delimited
from cte t
group by t.id
id
letters_delimited
letters_not_delimited
1
T,g,i,f
Tgif
2
I,w,2,s,o,i,c
Iw2soic
fiddle here
You can extend your approach with recursion
WITH cte_name AS (
select CONVERT(nvarchar(max), substring(column_name, 1, 1)) conc,
column_name n,
charindex(' ', column_name, 0) pos
from table_name
UNION ALL
select conc + substring(n, pos + 1, 1) as conc,
n,
charindex(' ', n, pos + 1) pos
from cte_name where pos > 0
)
SELECT *
FROM cte_name
where pos = 0;

Truncate specific number of characters in SQL cells

I have Description column in a table
Description
---------------
AA Check
B1 Check
RD/AA Check
WD_FA Examine
FF Examine
AA Pass
B2 Check
Examine
The desired output
Description
---------------
Check
Examine
Pass
Basically a case statement where it truncates from the left side of the cell. NOTE that the list goes on with different names and conditions, and some cells do not need modification (like the last row), so something similar to a case statement but not returning NULL if I did not specify the condition
Thank you
This removes the data up to the 1st space
case when x like '% %'
then substring(x, charindex(' ', x) +1, 8000)
else x
end
'AA Examine Device' -> 'Examine Device'
And this extracts the last word:
case when x like '% %'
then right(x, charindex(' ', reverse(x)) -1)
else x
end
'AA Examine Device' -> 'Device'
Following the white space that you have, and using DISTINCT, this gets the last word following a white space or returns the word if it's the only word.
declare #Description table (Description varchar(64))
insert into #Description
values
('AA Check'),
('B1 Check'),
('RD/AA Check'),
('WD_FA Examine'),
('FF Examine'),
('AA Pass'),
('B2 Check'),
('Examine')
select distinct
right([Description],len([Description]) - charindex(' ',[Description]))
from #Description
You can do it like below :
select distinct substring(Description, charindex(' ', Description) + 1, len(Description))
The question is too broad, but you can use something like that
DECLARE #Product TABLE (
[Description] nvarchar(255),
Condition int
);
INSERT #Product ([Description], Condition)
select 'AA Check', 1 union all
select 'B1 Check', 2 union all
select 'RD/AA Check', 3 union all
select 'WD_FA Examine', 3 union all
select 'FF Examine', 4 union all
select 'AA Pass', 1 union all
select 'B2 Check', 5 union all
select 'Examine', 6
select
[Description],
case
when Condition = 1 then replace([Description],'AA ','')
when Condition = 2 then replace([Description],'B1 ','')
when Condition = 3 then ltrim(rtrim(right([Description],len([Description]) - 5)))
when Condition = 5 then replace([Description],'B2 ','')
when Condition = 6 then [Description]
else
''
end as 'NewDescription'
from #Product
I hope it helps 🙂
Perhaps something like this:
;WITH CTE (Column1) AS (
SELECT * FROM (
VALUES
(' AA Check '), (' B1 Check'), (' RD/AA Check '), (' WD_FA Examine '), (' FF Examine '),
(' AA Pass '), (' B2 Check '), (' Examine ')
) AS A (Column1)
)
SELECT
CASE WHEN CHARINDEX('Check', Column1) > 0 THEN SUBSTRING(Column1, CHARINDEX('Check', Column1), 5)
WHEN CHARINDEX('Examine', Column1) > 0 THEN SUBSTRING(Column1, CHARINDEX('Examine', Column1), 7)
WHEN CHARINDEX('Pass', Column1) > 0 THEN SUBSTRING(Column1, CHARINDEX('Pass', Column1), 4)
END AS Results
FROM CTE
It would be painful if you have a lot of variables though.
CREATE TABLE [A] ( [Description] VARCHAR(100));
INSERT [A]
VALUES
---------------
( 'AA Check' )
,( 'B1 Check' )
,( 'RD/AA Check' )
,( 'WD_FA Examine' )
,( 'FF Examine' )
,( 'AA Pass' )
,( 'B2 Check' )
,( 'Examine' )
,( 'Examine Device' );
SELECT DISTINCT
CASE
WHEN [Description] COLLATE Latin1_General_BIN LIKE '[A-Z][a-z]%' THEN
[Description]
WHEN [Description] COLLATE Latin1_General_BIN LIKE '[A-Z][A-Z0-9]%' THEN
SUBSTRING([Description], CHARINDEX(' ', [Description]) + 1, 8000)
END AS [Description]
FROM
[A];
DROP TABLE [A];

SQL count string matches

Please take a look at this simple SQL server database :
I want the result to have 3 column, and the column "CountString" is the total number of string that matches ('this','is', 'count', 'example').
I have managed to detect those words using this query, but it can`t detect multiple words :
SELECT
productid,
NAME,
((CASE
WHEN Concat(' ', NAME, ' ') LIKE '% this %' THEN 1
ELSE 0
END) + (CASE
WHEN Concat(' ', NAME, ' ') LIKE '% is %' THEN 1
ELSE 0
END) + (CASE
WHEN Concat(' ', NAME, ' ') LIKE '% count %' THEN 1
ELSE 0
END) + (CASE
WHEN
Concat(' ', NAME, ' ') LIKE '% example %' THEN 1
ELSE 0
END)) AS CountString
FROM product;
However, if the name for productID 1 is "this is count this example". I want it to be counted as 5. Could you solve this ?
Create Table product(productid int, NAME varchar(100))
Insert Into product Values(1,'this is this example')
Insert Into product Values(2,'this is this this count this example')
SELECT productid,count(*) as CountString
FROM
(
SELECT A.[productid],
Split.a.value('.', 'VARCHAR(100)') AS String
FROM (SELECT [productid],
CAST ('<M>' + REPLACE([NAME], ' ', '</M><M>') + '</M>' AS XML) AS String
FROM product) AS A
CROSS APPLY String.nodes ('/M') AS Split(a)
) As Word
WHERE String in ('this','is','count','example')
Group by productid
Try this
DECLARE #TableString TABLE(ID INT IDENTITY,String nvarchar(max))
INSERT INTO #TableString(String)
SELECT 'this is count this example' UNION ALL
SELECT 'Bearing Ball' UNION ALL
SELECT 'BB Ball Bearing ' UNION ALL
SELECT 'this is example'
-- Here the delimeter is space
SELECT id AS productid, COUNT(stringValue) AS StringValueCount FROM
(
SELECT id ,
Split.a.value('.', 'VARCHAR(1000)') AS stringValue
FROM (
SELECT id,CAST('<S>' + REPLACE(String, ' ', '</S><S>') + '</S>' AS XML) AS String
FROM #TableString
) AS A
CROSS APPLY String.nodes('/S') AS Split(a)
)Dt
WHERE dt.stringValue in ('this','is','count','example')
GROUP BY id
Result
productid StringValueCount
-----------------------------
1 5
4 3

Split Strings into columns in SQL Server

I have a name field in Students table which is a comma separated string in format "LastName, FirstName, Middle Name".While doing a select statement in SQL query I need to break this up into separate fields.How can I achieve this in SQL?.Some times Middle intial won't be available.
SUBSTRING(Name,CHARINDEX(',',Name,1)+2,LEN(Name)) AS FirstName,
SUBSTRING(Name,1,CHARINDEX(',',Name,1)-1) AS LastName,
Above code works fine when there is no Middle name.
This should give you what you need:
declare #tmp table (fullname varchar(100));
insert #tmp values('James, Billy, L'), ('John, Snow');
select
fullname
, [Last Name]
, case
when charindex(',', Remainder, 0) > 0
then ltrim(substring(Remainder, 0, charindex(',', Remainder, 0)))
else ltrim(Remainder)
end [First Name]
, case
when charindex(',', Remainder, 0) = 0
then NULL
else ltrim(substring(Remainder, charindex(',', Remainder, 0) + 1, len(Remainder)))
end [Middle Name]
from
(select
fullname
, substring(fullname, 0, charindex(',', fullname, 0)) [Last Name]
, substring(fullname, charindex(',', fullname, 0) + 1, len(fullname)) [Remainder]
from #tmp) result;
First just find the occurrences of comma(,) in the string. Then use CASE expression to get the number of comma. If there is 2 comma then we can assume that middle name is also there. If 1 then only first name and last name. Then use the combinations of LEFT, RIGHT, SUBSTRING, CHARINDEX string functions.
Query
select t.name,
left(
t.name,
charindex(',', t.name, 1) - 1
) last_name,
case t.comma_num
when 2
then substring(
t.name,
charindex(',', t.name, 1) + 1,
len(name) -
(charindex(',', t.name, 1) + 1) - charindex(',', reverse(t.name), 1) + 1
)
when 1
then right(
t.name,
charindex(',', reverse(t.name), 1) - 1
)
else null end as first_name,
case t.comma_num
when 2
then right(
t.name, charindex(',', reverse(t.name), 1) - 1
)
else null end as middle_name
from (
select name,
len(name) - len(replace(name, ',', '')) comma_num
from [your_table_name]
)t;
Find demo here
Use CTE and SUBSTRING AND CHARINDEX funntions
DECLARE #Name VARCHAR(100) = 'James, Billy, L'
--DECLARE #Name VARCHAR(100) = 'James, '', L'
;WITH _CTE ( SplitedNames ,RemainStr) AS
(
SELECT SUBSTRING(#Name,0,CHARINDEX(',',#Name)),
SUBSTRING(#Name,CHARINDEX(',',#Name)+1,LEN(#Name))
UNION ALL
SELECT CASE WHEN CHARINDEX(',',RemainStr) = 0 THEN RemainStr ELSE
SUBSTRING(RemainStr,0,CHARINDEX(',',RemainStr)) END,
CASE WHEN CHARINDEX(',',RemainStr) = 0 THEN '' ELSE
SUBSTRING(RemainStr,CHARINDEX(',',RemainStr)+1,LEN(RemainStr))
END
FROM _CTE
WHERE RemainStr <> ''
)
SELECT SplitedNames FROM _CTE

parsing first and last names from sql table

I have a column in my SQL Server 2008 database that contains c/o Full Name. I'm having issues getting the First and Last names separated. I have the c/o in its own column, but I need the First/Last Names. I know that there is an issue with the second and third case statement, but I'm not sure what I need to change. Should I be storing index variables somewhere to reference them?
Declare #t table ( [name] varchar(100) )
INSERT INTO #t ( Name )
SELECT Street1 FROM tblPeople
WHERE CO = 'Y' AND LastName NOT LIKE 'SUMMERHAVEN INC' AND Street1 Like '%c/o%'
SELECT
[name],
CHARINDEX(' ', [name]),
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
LEFT([name],CHARINDEX(' ',[name])-1)
ELSE
[name]
END as CO,
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
SUBSTRING([name],CHARINDEX(' ',[name])+1, ( LEN([name]) - CHARINDEX(' ',[name])+1) )
ELSE
NULL
END as FIRST_NAME,
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
SUBSTRING([name],CHARINDEX(' ',[name])+1, ( LEN([name]) - CHARINDEX(' ',[name])+1) )
ELSE
NULL
END as LAST_NAME
FROM #t
To my surprise, PARSENAME() was available in 2008
Consider the following
Declare #YourTable table (Name varchar(50))
Insert Into #YourTable values
('c/o Cher')
,('c/o John Smith')
,('John Smith')
Select *
,FirstName=parsename(replace(ltrim(rtrim(replace(name,'c/o',''))),' ','.'),2)
,LastName =parsename(replace(ltrim(rtrim(replace(name,'c/o',''))),' ','.'),1)
From #YourTable
Returns
Name FirstName LastName
c/o Cher NULL Cher
c/o John Smith John Smith
John Smith John Smith
Disclosure: this is a bad idea to parse the data like this, but here you go:
Declare #t table ( [name] varchar(100) )
insert into #t ( Name ) values ('c/o Full Name')
SELECT
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
LEFT([name],CHARINDEX(' ',[name])-1)
ELSE
[name]
END as CO,
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
SUBSTRING([name],CHARINDEX(' ',[name])+1, CHARINDEX(' ',[name]) )
ELSE
NULL
END as FIRST_NAME,
CASE WHEN CHARINDEX(' ', [name]) > 0 THEN
SUBSTRING([name],CHARINDEX(' ',[name], CHARINDEX(' ',[name])+1), len([name]))
ELSE
NULL
END as LAST_NAME
FROM #t
Here's an approach using Common Table Expressions which so that the logic for finding the spaces to break on is reasonably self-documenting.
Declare #t table ( [name] varchar(100) )
insert into #t ( Name )
select 'one two three'
union select 'a bc def'
union select 'one two'
union select 'one'
;with cte1 as
(
select name
,charindex(' ', name) FirstSpace
from #t
)
, cte2 as (
select name
, FirstSpace
,charindex(' ', name, FirstSpace+1) SecondSpace
from cte1
)
select name
, FirstSpace
, SecondSpace
, case when FirstSpace=0 then name else substring(name, 1, FirstSpace-1) end Company
, case when SecondSpace=0 then null else substring(name, FirstSpace+1, SecondSpace-FirstSpace-1) end FirstName
, case when SecondSpace=0 or SecondSpace=len(name) then null else substring(name, SecondSpace+1, len(name)-SecondSpace) end LastName
from cte2