0

I have words separated with a space in a column like apple orange banana I need the first letters as the result will be something like :

aob
Christophe Debove
  • 6,088
  • 20
  • 73
  • 124
  • 3
    What version of `sql server` are you using? – Ryan Wilson Jan 07 '19 at 13:23
  • @RyanWilson Microsoft SQL Server 2012 , I updated the tag – Christophe Debove Jan 07 '19 at 13:31
  • 1
    I think you might want to take a look at [this question](https://stackoverflow.com/questions/46902892/string-split-in-sql-server-2012). As STRING_SPLIT would probably have been recommanded if you were on a higher version of SQL Server. – Yann G Jan 07 '19 at 13:36
  • 1
    What have you tried so far? Could you please post your attempts? – Thom A Jan 07 '19 at 13:36
  • String processing is *not* T-SQL's strong suit. Is there a reason this has to be done in the database? – Damien_The_Unbeliever Jan 07 '19 at 13:39
  • I try to insert in a FullName column of a table, from another table the name(watson) and firstname(mary jane) from another column, repecting this format MJ.WASTSON. @Damien_The_Unbeliever I don't want to do write a program to extract transform and insert data. – Christophe Debove Jan 07 '19 at 13:52

4 Answers4

1

First, split your text. I recommend some function:

CREATE FUNCTION Split(@text nvarchar(MAX),@separator nvarchar(MAX))
RETURNS TABLE AS RETURN
WITH Indexed AS
(
    SELECT 1 N, CAST(1 AS bigint) S, CHARINDEX(@separator, @text, 1) E WHERE @text IS NOT NULL
    UNION ALL
    SELECT N+1, E+DATALENGTH(@separator)/2, CHARINDEX(@separator, @text, E+DATALENGTH(@separator)/2) FROM Indexed WHERE E>S
), Token AS
(
    SELECT N, SUBSTRING(@text, S, CASE WHEN E=0 THEN DATALENGTH(@text)/2 ELSE E-S END) T FROM Indexed
)
SELECT * FROM Token

If you are using SQL 2016 and greater, use STRING_SPLIT instead.

Then, you can select first character of every word and join. See following example:

DECLARE @Sample TABLE (T nvarchar(100));
INSERT @Sample VALUES (N'apple orange banana'),(N'dog cat');

SELECT (SELECT SUBSTRING(T,1,1) [*] FROM Split(T,N' ') FOR XML PATH(''))
FROM @Sample

Result:

(no column name)
------
aob
dc
Paweł Dyl
  • 8,888
  • 1
  • 11
  • 27
  • Just to be a smart aleck ;-) `STRING SPLIT()` migth not return in the expected order, at least this is not guaranteed. With SQL-Server 2016 it's better to use `OPENJSON` and transform the CSV into a JSON array first. The `key` will reflect the item's position. Btw: My answer does the concatenation within XML. Within XML the element's order is part of the document and therefore guaranteed. [Here's an `OPENJSON` example with performance comparison](https://stackoverflow.com/a/51401153/5089204) – Shnugo Jan 07 '19 at 16:08
0

Just another option using a little XML. You could also use ParseName() provided you trap any periods in the string.

Example

Declare @YourTable table(ID int,LastName varchar(50),FirstName varchar(50))
Insert Into @YourTable values
(1,'Waston','Mary Jane')

Select A.ID
      ,NewValue = upper(
                      concat(
                            xmlData.value('/x[1]','varchar(1)')
                           ,xmlData.value('/x[2]','varchar(1)')
                           ,xmlData.value('/x[3]','varchar(1)')
                           ,xmlData.value('/x[4]','varchar(1)')
                           ,'.'
                           ,LastName
                       )
                   )
 From  @YourTable A
 Cross Apply ( values (convert(xml,'<x>' + replace(A.FirstName,' ','</x><x>')+'</x>' )) ) B(xmlData)

Returns

ID  NewValue
1   MJ.WASTON

EDIT - Added ParseName() option

Select A.ID
      ,NewValue = upper(concat(Pos1,Pos2,Pos3,Pos4,'.',LastName))
 From  @YourTable A
 Cross Apply (
                Select Pos1 = left(parsename(tStr,4),1)
                      ,Pos2 = left(parsename(tStr,3),1)
                      ,Pos3 = left(parsename(tStr,2),1)
                      ,Pos4 = left(parsename(tStr,1),1)
                 From  ( values(replace(FirstName,' ','.'))) B1(tStr)
             ) B
John Cappelletti
  • 79,615
  • 7
  • 44
  • 66
0

If you declare REGEX function in your DB (not native with SQL SERVER).

Using regexp_replace

select regexp_replace('apple orange banana','(\\w)(\\w* ?)','$1')

return

aob
aaDev
  • 143
  • 6
0

I think the shortest will be this:

Here a mockup-table with two rows to simulate your issue:

DECLARE @mockup TABLE(ID INT IDENTITY,YourWords VARCHAR(100));
INSERT INTO @mockup VALUES('apple orange banana'),('one two three');

--That is the query:

SELECT m.ID
      ,REPLACE(Casted.query('for $w in /x return substring($w,1,1)').value('.','varchar(max)'),' ','')
FROM @mockup m
CROSS APPLY(SELECT CAST('<x>' + REPLACE(m.YourWords,' ','</x><x>') + '</x>' AS XML)) A(Casted);

The idea behind:
The string apple orange banana is tranformed to <x>apple</x><x>orange</x><x>banana</x> and is casted to XML, which allows to use XQuery.
Now we use .query() on the XML with a simple FLWOR statement. It tells the engine: run through each value of /x and return just the first letter. Calling value() on this with a . as XPath will return the values in one.
We need a final REPLACE() to get rid of blanks, which would otherwise appear as a o b instead of aob.

Shnugo
  • 66,100
  • 9
  • 53
  • 114