Функция SQL Split - PullRequest
       9

Функция SQL Split

2 голосов
/ 20 мая 2010

Я ищу способ сделать это ...

SELECT FirstName, LastName, Split(AddressBlock, '  ', 1), Split(AddressBlock, ' ', 2), PostCode 
FROM Contacts

Аргументы, которые я хочу передать: ...

  1. Адрес
  2. Разделитель (в текущей ситуации требуется 2 пробела, но это может быть запятая или пробел, за которым следует запятая) или что-то еще (меняется).
  3. Часть адреса, которую я хочу вернутьвсегда нужны все части результата разделения).

Кажется, я могу найти несколько примеров функций разделения в Интернете, но они возвращают таблицу, содержащую весь набор частей разделения.

Мои навыки работы с SQL не так уж и хороши, поэтому мне нужен очень простой ответ.Я всегда работаю с данными nvarchar, и эту функцию нужно многократно использовать.

Ответы [ 3 ]

4 голосов
/ 20 мая 2010

Если вы хотите, чтобы пользовательская функция делала это, это должно работать. Не так красиво, но ...

CREATE FUNCTION dbo.SplitStringPart (
    @input nvarchar(MAX),
    @separator nvarchar(10),
    @index int
) RETURNS nvarchar(MAX)
BEGIN

DECLARE @counter int,
        @position int,
        @oldposition int,
        @separatorlength int,
        @result nvarchar(MAX)

SET @separatorlength = DATALENGTH(@separator) / 2
IF @separatorlength = 0 RETURN NULL

SET @result = NULL

SET @counter = 1
SET @position = -2

WHILE (@counter <= @index)
BEGIN

    SET @oldposition = @position
    SET @position = CHARINDEX(@separator, @input, @position + 1)
    IF @position = 0 AND @counter < @index
    BEGIN
        SET @oldposition = 0
        BREAK
    END
    SET @counter = @counter + 1

END

IF @oldposition = 0 AND @position = 0
    RETURN NULL
ELSE IF @oldposition < 0
BEGIN
    IF @position = 0 AND @index = 1
        SET @result = @input
    ELSE
        SET @result = SUBSTRING(@input, 0, @position)
END
ELSE IF @position <= 0
    SET @result = SUBSTRING(@input, @oldposition + @separatorlength, LEN(@input) - @oldposition - @separatorlength)
ELSE
    SET @result = SUBSTRING(@input, @oldposition + @separatorlength, @position - @oldposition - @separatorlength)

RETURN @result

END
GO
1 голос
/ 20 мая 2010

Это не красиво, но добавьте к вам SQL-выражение, и оно должно работать:

CASE 
WHEN charindex(' ', substring(AddressBlock, (charindex(' ', AddressBlock) + 1), len(AddressBlock))) > 0 THEN substring(AddressBlock, (charindex(' ', AddressBlock) + 1), charindex(' ', substring(AddressBlock, (charindex(' ', AddressBlock) + 1), len(AddressBlock))) - 1)
ELSE substring(AddressBlock, (charindex(' ', AddressBlock) + 1), len(AddressBlock))    
END AS 'Address 1', 
CASE WHEN charindex(' ', substring(AddressBlock, (charindex(' ', AddressBlock) + 1), len(AddressBlock))) > 0 THEN substring(AddressBlock, charindex(' ', AddressBlock) + charindex(' ', substring(AddressBlock, (charindex(' ', AddressBlock) + 1), len(AddressBlock))) + 1, Len(AddressBlock))
ELSE ''
END AS 'Address 2'
0 голосов
/ 17 марта 2017

Вот мой вариант ответа. Это НАМНОГО быстрее и надежнее. Нет необходимости возиться с подстроками, хариндексами и т. Д.

CREATE FUNCTION [dbo].[SplitArray]
(
    @RowToSplit nvarchar(MAX),
    @Delimeter nvarchar(MAX)
)  
RETURNS @RtnValue table (ID bigint IDENTITY, Data nvarchar(MAX)) 
AS  
BEGIN 
    DECLARE @xml xml
    SET @xml = '<field>' + REPLACE(@RowToSplit, @Delimeter, '</field><field>') + '</field>'
    INSERT INTO @RtnValue(data)
    SELECT  tbl.c.value('.','nvarchar(max)')
    FROM @xml.nodes('/field') tbl(c)
    RETURN
END

Вы бы просто использовали результирующие значения разделения в таблице, например:

SELECT Data FROM dbo.SplitArray('this is great',' ')

Это вернет:

Data
============
this
is
great
...