7

I've a table with entries like this.

    MachineName
-----------------------

    Ab bb zecos
    a zeng
    zeng
    empty

4 rows in a table.

How can i seperate those 4 rows to get output like.

       M1       M2       M3
-----------------------------------
       Ab       bb      zecos
       a        zeng     NULL
       zeng     NULL     NULL
       NULL     NULL     NULL
user614978
  • 317
  • 2
  • 4
  • 10
  • 1
    This isn't by chance so you can apply tags to elements, would it? – Brad Christie Jun 25 '12 at 07:50
  • @BradChristie Didn't get you! – user614978 Jun 25 '12 at 07:53
  • 1
    As in you didn't understand the question? I'm asking if you're primary purpose is to apply tags to items (almost like a blog does to posts) and now you're trying to retrieve them back. – Brad Christie Jun 25 '12 at 07:57
  • Maybe this post will help: [http://stackoverflow.com/questions/2647/split-string-in-sql](http://stackoverflow.com/questions/2647/split-string-in-sql) – ekholm Jun 25 '12 at 08:39
  • Create a temp table with M1, M2, M3 columns, get machine names, split names by spaces and insert row the in a new table – MSUH Jun 25 '12 at 08:44
  • i have sting nt:865067021846160:2:8.5.05:1,1,20161010102239.000,18.580423,73.815948,549.700,0.28,33.6,11:101:100:0:0:0:FF:146:25} i want to separate by : into column – Shridhar Oct 13 '16 at 07:49

5 Answers5

12

Instead of using split function there is a function called ParseName which returns the specified part of the object which spilts the string delimated by . Please go through the ParseName link which helped me in writing this query

Declare @Sample Table
(MachineName varchar(max))

Insert into @Sample
values 
('Ab bb zecos'),('a Zeng')


  SELECT 
  Reverse(ParseName(Replace(Reverse(MachineName), ' ', '.'), 1)) As [M1]
 , Reverse(ParseName(Replace(Reverse(MachineName), ' ', '.'), 2)) As [M2]
 , Reverse(ParseName(Replace(Reverse(MachineName), ' ', '.'), 3)) As [M3]

  FROM  (Select MachineName from @Sample
  ) As [x] 
Jonathan S.
  • 5,837
  • 8
  • 44
  • 63
praveen
  • 12,083
  • 1
  • 41
  • 49
  • 2
    I recall something about PARSENAME not allowing more than 4 items (since it's used for object names and 4 parts is the maximum length of an object identifier) - so you could use this as long as you remember that :) – Charleh Jun 25 '12 at 08:54
  • Yeah thanks for reminding me but i think OP mentioned in his question having only 3 columns – praveen Jun 25 '12 at 08:59
  • perfect... this is what i also exactly want.. thanks a ton :) – user2768132 Nov 14 '17 at 08:58
  • If segments of the split are blank you may get no returned result for all of the segments. To avoid this I do the following (I use + as its not in the column but you can use any unused character): Replace(ParseName(Replace(DELADD.CONTACT_VALUE, CHAR(10), '+.+'), 3),'+','') – Craig P May 05 '19 at 13:45
6

Try this one:

    CREATE FUNCTION [dbo].[SplitIndex](@Delimiter varchar(20) = ' ', @Search varchar(max), @index int)
    RETURNS varchar(max)
    AS
    BEGIN
          DECLARE @ix int,
                      @pos int,
                    @rt varchar(max)

          DECLARE @tb TABLE (Val varchar(max), id int identity(1,1))

          SET @ix = 1
          SET @pos = 1


          WHILE @ix <= LEN(@search) + 1 BEGIN

                SET @ix = CHARINDEX(@Delimiter, @Search, @ix)

                IF @ix = 0
                      SET @ix = LEN(@Search)
                ELSE
                      SET @ix = @ix - 1

                INSERT INTO @tb
                SELECT SUBSTRING(@Search, @pos, @ix - @pos + 1)

                SET @ix = @ix + 2
                SET @pos = @ix
          END

          SELECT @Rt = Val FROM @Tb WHERE id = @index
          RETURN @Rt     
    END

Use like so:

SELECT dbo.SplitIndex(' ', 'hello World', 1)

Combine that with Dems answer and you should be good to go

(Note it will return NULL if the specified index does not exist)

e.g.

SELECT dbo.SplitIndex(' ', 'Hello World', 3)  

would return NULL because index 3 does not exist

Not sure what performance is like though, I just modified a table valued split function that I'd done so it might be worth rewriting to be more like the MySql version

Charleh
  • 13,749
  • 3
  • 37
  • 57
  • 1
    Thank you, you saved me, this is the best solution. All above answer using PARSENAME has a drawback, of limitation no more then 4 values – Satinder singh Feb 20 '21 at 20:07
4

Use Parsename() function

with cte as(
    select 'Aria Karimi' as FullName
    Union
    select 'Joe Karimi' as FullName
    Union
    select 'Bab Karimi' as FullName
)

SELECT PARSENAME(REPLACE(FullName,' ','.'),2) as Name, PARSENAME(REPLACE(FullName,' ','.'),1) as Family from cte

Result

Name    Family
-----   ------
Aria    Karimi
Bab     Karimi
Joe     Karimi
Mohammad Karimi
  • 4,151
  • 2
  • 21
  • 19
2
DECLARE @Tmp TABLE (empid INT,joined nchar(10))

INSERT @Tmp SELECT 1,'1990, 1111' 
INSERT @Tmp SELECT 2,'2000, 2222' 

INSERT @Tmp SELECT 3,'1993, 3333' 

INSERT @Tmp SELECT 4,'1899, 4444' 
INSERT @Tmp SELECT 5,'1999, 5555' 

INSERT @Tmp SELECT 6,'2001, 6666 ' 


--Using PARSENAME 

SELECT empid, joined,
       PARSENAME(REPLACE(joined,',','.'),2) join1, 
       PARSENAME(REPLACE(joined,',','.'),1) join2 
FROM @Tmp
xlm
  • 6,854
  • 14
  • 53
  • 55
l.lijith
  • 413
  • 6
  • 19
-7

If you are programming in C++, please do:

#include <cstring>
#include <iomanip>

using namespace std;
int main () {
string machine[12];
for (int i = 0; i < 12; i++) {
    if (machine[i] == "")
        machine[i] = "NULL";
}

for (int i = 0; i < 3; i++) {
    cout << setw(10) << machine[i] << setw(10) << machine[i+1] << setw(10) << machine[i+2] << endl;
}
return 1;
}
monkeyMoo
  • 173
  • 1
  • 1
  • 7