Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Функция, которая делит строку на слова  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
где бы взять?

Т.е. на входе строка, на выходе список слов
29 апр 11, 12:28    [10586015]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
Вини - ну загляни в факу а не ленись
29 апр 11, 12:32    [10586036]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
не нашел....

вот есть такое. но здесь только один роазделитель указывается, а хотелось бы несколько, типа ' ', ',', '.'


CREATE FUNCTION [dbo].[fn_Split] (@text NVARCHAR(MAX), @delimiter NVARCHAR(20) = N' ')

	RETURNS @Strings TABLE (
		position INT IDENTITY PRIMARY KEY
		, value NVARCHAR(MAX)
		)

AS BEGIN
	DECLARE @index int
	SET @index = -1
if @delimiter = N' '
	set @text = RTRIM(LTRIM(@text))

	WHILE (LEN(@text) > 0) 
	BEGIN
		SET @index = CHARINDEX(@delimiter , @text)
		IF (@index = 0) AND (LEN(@text) > 0) BEGIN  
			INSERT INTO @Strings VALUES (@text)
			BREAK 
		END 
		IF (@index > 1) BEGIN
			INSERT INTO @Strings VALUES (LEFT(@text, @index - 1))
			SET @text = RIGHT(@text, (LEN(@text) - @index))
		END
		ELSE SET @text = RIGHT(@text, (LEN(@text) - @index))
	END
	RETURN
END
29 апр 11, 12:38    [10586075]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
aleks2
Guest
CREATE function [dbo].[f_StrToTableEx](@str varchar(8000), @delimiter varchar(64)=',')
returns table as
return(
WITH str_nums ( n1, n2, Number ) 
AS 
( 
select  1-LEN(@delimiter) as n1, charindex(@delimiter, @str+@delimiter) as n2, 0 as Number  
UNION ALL 
select n2 as n1, charindex(@delimiter, @str+@delimiter, n2+LEN(@delimiter)) as n2, Number+1 as Number
from str_nums
WHERE n2<len(@str)
) 
SELECT SUBSTRING(@str, n1+LEN(@delimiter), n2-n1-1) as Value, Number, n1+1 as StartPosition FROM str_nums
)

А множественность "роазделителей" решается REPLACE-ом на один.
29 апр 11, 12:42    [10586095]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
DeColo®es
Member

Откуда: Москва
Сообщений: 5499
Блог
Вот буквально сейчас этот код был открыт в редакторе.

IF OBJECT_ID('dSequence') IS NOT NULL DROP TABLE dSequence
GO
CREATE TABLE 
    dSequence
    (
    ID int constraint PK_Sequence PRIMARY key clustered with fillfactor=100
    )
--     Заполняем (2M чисел)
INSERT INTO dSequence(ID) 
    SELECT v1.number + v2.number*2048
    FROM master..spt_values v1
    inner join master..spt_values v2
		on v2.number < 1024
		and v2.type='P'
    WHERE v1.type='P'
GO
-- Функции разбивки на слова
IF OBJECT_ID('dbo.fnv_StrToList') IS NOT NULL DROP FUNCTION dbo.fnv_StrToList
GO
CREATE FUNCTION dbo.fnv_StrToList(@str varchar(max), @splitter char(1))
RETURNS TABLE
AS
RETURN(
    SELECT 
        SUBSTRING(@str, ID, ISNULL(NULLIF(CHARINDEX(@splitter, @str, ID), 0), LEN(@str)+1) - ID) as element,
		ID as elementPos
    FROM dSequence with(nolock)
    WHERE ID >= 1 AND ID <= convert(int, LEN(@str))
    AND (convert(char(1), SUBSTRING(@str, ID-1, 1)) = @splitter)
    AND CHARINDEX(@splitter, @str, ID) > ID
    )
go
declare @str varchar(max)
set @str  = 'j1k2h3b123,,.412m,.34m,12341.23,.m4'
select * from dbo.fnv_StrToList(@str, ',') fvstl
29 апр 11, 12:51    [10586152]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
invm
Member

Откуда: Москва
Сообщений: 9442
DeColo®es,

Будет неправильно работать для данных с концевым пробелом
set @str  = 'j1k2h3b123,,.412m,.34m,12341.23,.m4 '
29 апр 11, 13:47    [10586610]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
DeColo®es
Member

Откуда: Москва
Сообщений: 5499
Блог
invm
DeColo®es,
Будет неправильно работать для данных с концевым пробелом
Дело не в концевом пробеле.
Там просто все неправильно.

Правильно так:
alter FUNCTION Utils.fnv_StrToList(@str varchar(max), @splitter char(1))
RETURNS TABLE
AS
RETURN(
    SELECT 
        SUBSTRING(@str, ID, ISNULL(NULLIF(CHARINDEX(@splitter, @str, ID), 0), LEN(@str)+1) - ID) as element,
		ID as elementPos
    FROM Utils.d_Sequence with(nolock)
    WHERE ID >= 1 AND ID <= convert(int, LEN(@str))
    AND (convert(char(1), case when ID=1 then ',' else SUBSTRING(@str, ID-1, 1) end) = @splitter)
)
29 апр 11, 17:46    [10588690]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
DeColo®es
Member

Откуда: Москва
Сообщений: 5499
Блог
PS Имя функции и таблицы поправить на свой вкус.
29 апр 11, 17:46    [10588696]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
DeColo®es
PS Имя функции и таблицы поправить на свой вкус.


(y)
29 апр 11, 17:51    [10588726]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
invm
Member

Откуда: Москва
Сообщений: 9442
DeColo®es
invm
DeColo®es,
Будет неправильно работать для данных с концевым пробелом
Дело не в концевом пробеле.
Там просто все неправильно.

Правильно так:
alter FUNCTION Utils.fnv_StrToList(@str varchar(max), @splitter char(1))
RETURNS TABLE
AS
RETURN(
    SELECT 
        SUBSTRING(@str, ID, ISNULL(NULLIF(CHARINDEX(@splitter, @str, ID), 0), LEN(@str)+1) - ID) as element,
		ID as elementPos
    FROM Utils.d_Sequence with(nolock)
    WHERE ID >= 1 AND ID <= convert(int, LEN(@str))
    AND (convert(char(1), case when ID=1 then ',' else SUBSTRING(@str, ID-1, 1) end) = @splitter)
)


Ну так концевые пробелы все равно режет
Нет, конечно, они редко когда есть и нужны, но все-таки не дело искажать данные в функции.
29 апр 11, 18:16    [10588878]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
iljy
Member

Откуда:
Сообщений: 8711
invm,

замените LEN на DATALENGTH
29 апр 11, 18:20    [10588905]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
DeColo®es
Member

Откуда: Москва
Сообщений: 5499
Блог
iljy
invm,
замените LEN на DATALENGTH
+1
Я пока не встречал требований по сохранению пробелов, сознательно так оставил.
29 апр 11, 18:23    [10588935]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
invm
Member

Откуда: Москва
Сообщений: 9442
iljy,
Зачем мне что-то менять в чужом коде? У меня есть собственный вариант, который работает корректно.

DeColo®es,
Ваше право считать, что в данном случае сайд-эффекты допустимы. Мое же ИМХО: отсутствие сайд-эффектов является неоспоримым плюсом.
29 апр 11, 18:55    [10589095]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
iap
Member

Откуда: Москва
Сообщений: 47009
SET NOCOUNT ON;
USE tempdb;
IF OBJECT_ID(N'dbo.ParseString') IS NOT NULL DROP FUNCTION dbo.ParseString;
GO
CREATE FUNCTION dbo.ParseString(@S VARCHAR(MAX), @Delimiters VARCHAR(MAX))
RETURNS TABLE AS RETURN
SELECT N,S
FROM
(
 SELECT V.number,SUBSTRING(@S COLLATE Cyrillic_General_CI_AI,V.number,
  (
   SELECT MIN(VV.number)
   FROM master.dbo.spt_values VV
   WHERE VV.type='P' AND VV.number BETWEEN V.number AND LEN(@S)+1
   AND CHARINDEX(SUBSTRING(@S+LEFT(@Delimiters,1),VV.number,1),@Delimiters)>0
  )-V.number
 )
 FROM master.dbo.spt_values V
 WHERE V.type='P' AND V.number BETWEEN 1 AND LEN(@S)+1
 AND CHARINDEX(SUBSTRING(LEFT(@Delimiters,1)+@S,V.number,1),@Delimiters)>0
)T(N,S)
WHERE S>'';
GO
SELECT * FROM dbo.ParseString('|qaz|234455|0 |31.03.2009|t[rh]th | | ','| ,.[]()'+CHAR(9)+CHAR(10)+CHAR(13)) ORDER BY N;
29 апр 11, 19:28    [10589208]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
DeColo®es
Member

Откуда: Москва
Сообщений: 5499
Блог
invm
отсутствие сайд-эффектов является неоспоримым плюсом.
Хм.
В данном случае соглашусь. Проблема в том, что проблемы именно в конце последней строки обрезаются, остальные - остаются.
29 апр 11, 19:37    [10589224]     Ответить | Цитировать Сообщить модератору
 Re: Функция, которая делит строку на слова  [new]
invm
Member

Откуда: Москва
Сообщений: 9442
DeColo®es
Проблема в том, что проблемы именно в конце последней строки обрезаются, остальные - остаются.

Именно на этот факт я и хотел обратить внимание.
1 май 11, 10:10    [10592003]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить