Declare @text='i #want to extract all #hastag out of this string, #delhi #Traffic'
Желаемый результат будет в строке: "#want,#hastag,#delhi,#Traffic"
или таблице.Как извлечь хэштеги из строки в T-SQL
Declare @text='i #want to extract all #hastag out of this string, #delhi #Traffic'
Желаемый результат будет в строке: "#want,#hastag,#delhi,#Traffic"
или таблице.Как извлечь хэштеги из строки в T-SQL
Попробуй как этот
Declare @text VARCHAR(100)='i #want to extract all #hastag out of this string, #delhi #Traffic';
WITH Casted(ToXml) AS (SELECT CAST('<x>' + REPLACE((SELECT @text AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML))
SELECT SUBSTRING(x.value('.','nvarchar(max)'),2,1000)
FROM Casted
CROSS APPLY ToXml.nodes('x[substring((./text())[1],1,1)="#"]') AS A(x)
результат (я срезал #
, просто забрать внешний SUBSTRING
, если вам это нужно)
want
hastag
delhi
Traffic
Или как строка вы разместили, как и ожидалось выход:
Попробуйте, как этот
Declare @text VARCHAR(100)='i #want to extract all #hastag out of this string, #delhi #Traffic';
WITH Casted(ToXml) AS (SELECT CAST('<x>' + REPLACE((SELECT @text AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML))
SELECT STUFF(
(
SELECT ','+x.value('.','nvarchar(max)')
FROM Casted
CROSS APPLY ToXml.nodes('x[substring((./text())[1],1,1)="#"]') AS A(x)
FOR XML PATH(''),TYPE
).value('.','nvarchar(max)'),1,1,'')
Результат
#want,#hastag,#delhi,#Traffic
Это в основном код функции split для SQL-сервера, вы можете найти его в любом месте сети. В принципе, я хотел бы использовать сплит функции первого, разделить целое предложение словами, то просто выберите те, которые получили «#» символ с ними
declare @String nvarchar(200) = 'i #want to extract all #hastag
out of this string, #delhi #Traffic'
DECLARE @Delimiter char(1) = ' '
if object_id('tempdb..#slicedWords') is not null drop table #slicedWords
create table #slicedWords (word nvarchar(100))
declare @idx int
declare @slice varchar(8000)
select @idx = 1
if len(@String)<1 or @String is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@String)
if @idx!=0
set @slice = left(@String,@idx - 1)
else
set @slice = @String
if(len(@slice)>0)
insert
into #slicedWords(word) values(@slice)
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0
break
end
select * from #slicedWords where word like '%#%'
Или, если вы хотите в одной строке, изменить последний выбор с
select STUFF((SELECT ', ' + word
from #slicedWords where word like '%#%'
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
Если вы ищете функции разделения, вы найдете много лучших подходов, чем цикл 'WHILE'. – Shnugo
Правильно, я только что схватил первый, который дал мне Google, но в любом случае я бы пошел с решением @Shnugo в любом случае, так как я не знал об этой возможности, и кажется, что он намного чище, чем функция разделения. – Veljko89
Решение с использованием XML:
DECLARE @text nvarchar(max)='i #want to extract all #hastag out of this string, #delhi #Traffic'
SELECT STUFF(-- is used to separate all hashtags with commas
(
SELECT ',' + t.c.value('.','nvarchar(max)')
FROM (
--In this part we convert input text into XML
SELECT CAST('<a>'+REPLACE((SELECT @text as [*] FOR XML PATH('')),' ','</a><a>')+'</a>' as xml) as x
) as x
CROSS APPLY x.nodes('/a') as t(c)
WHERE t.c.exist('. [contains(., "#")]') = 1 --check if each part contains #
FOR XML PATH('')
),1,1,'')
Выход:
#want,#hastag,#delhi,#Traffic
Если есть '#' в другом месте, это тоже будет возвращено. И это сломается, если строка содержит запрещенные символы, такие как '<, >, &' и многие специальные символы, которые нуждаются в экранировании ... – Shnugo
@Shnugo _ Если в другом месте есть #, это тоже будет возвращено ._ - то же самое относится к ваши решения :) _And это сломается ..._ - да, это может быть переполнено с помощью 'SELECT @text как [*] FOR XML PATH ('')' в 'REPLACE'. – gofr1
* то же самое относится к вашему решению * Нет, предикат ''x [substring ((./ text()) [1], 1,1) =" # "]'' будет фильтровать только те, у которых есть '#' как первый символ. Ну, это будет включать * голый # *, который можно легко решить с помощью len-check. Вы правы со своей второй точкой, но в этом случае один ** должен ** использовать '..., TYPE) .value ('.', 'Nvarchar (max)')', чтобы перекодировать все сущности ... – Shnugo
Еще один подход, использующий Numbers таблицу
Declare @text varchar(max)='i #want to extract all #hastag out of this string, #delhi #Traffic'
select
substring(@text,number+1,
case when (charindex(' ',@text,number+1)-number+1)<=0 then 100 else charindex(' ',@text,number+1)-number end)
from
numbers
where number<len(@text) and substring(@text,number,1)=' '
and substring(@text,number+1,1)='#'
Выход:
#want
#hastag
#delhi
#Traffic
Привет, я исправил ненужную запятую и кстати: если вы поместите 'WITH numbers (number) AS SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM master..spt_values)' перед выбором, вы даже не нужна таблица физического номера – Shnugo
@ Шнуго: спасибо за исправление, у меня была таблица чисел, поэтому она использовалась – TheGameiswar
Shure, просто чтобы ваш образец был * автономным * ... – Shnugo
Используйте '' charindex' и substring'. Найдите первый символ '#' в строке, получите свою позицию с помощью 'charindex'. Затем получите положение первого символа пробега, начиная с этой позиции и получая часть строки между этими позициями. Повторяйте до конца строки. –
SQL Server на самом деле не лучший инструмент для этого. У вас есть доступ к .NET или Java? –
@TimBiegeleisen yes У меня есть доступ к .net. –