2017-02-13 1 views
3
Declare @text='i #want to extract all #hastag out of this string, #delhi #Traffic' 

Желаемый результат будет в строке: "#want,#hastag,#delhi,#Traffic" или таблице.Как извлечь хэштеги из строки в T-SQL

+0

Используйте '' charindex' и substring'. Найдите первый символ '#' в строке, получите свою позицию с помощью 'charindex'. Затем получите положение первого символа пробега, начиная с этой позиции и получая часть строки между этими позициями. Повторяйте до конца строки. –

+1

SQL Server на самом деле не лучший инструмент для этого. У вас есть доступ к .NET или Java? –

+0

@TimBiegeleisen yes У меня есть доступ к .net. –

ответ

5

Попробуй как этот

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 
+0

. Это на самом деле красивое решение ... – Veljko89

+0

Nice one! +1 с моей стороны! – gofr1

+0

спасибо .. это работает :) –

1

Это в основном код функции 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,'') 
+0

Если вы ищете функции разделения, вы найдете много лучших подходов, чем цикл 'WHILE'. – Shnugo

+0

Правильно, я только что схватил первый, который дал мне Google, но в любом случае я бы пошел с решением @Shnugo в любом случае, так как я не знал об этой возможности, и кажется, что он намного чище, чем функция разделения. – Veljko89

0

Решение с использованием 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 
+0

Если есть '#' в другом месте, это тоже будет возвращено. И это сломается, если строка содержит запрещенные символы, такие как '<, >, &' и многие специальные символы, которые нуждаются в экранировании ... – Shnugo

+0

@Shnugo _ Если в другом месте есть #, это тоже будет возвращено ._ - то же самое относится к ваши решения :) _And это сломается ..._ - да, это может быть переполнено с помощью 'SELECT @text как [*] FOR XML PATH ('')' в 'REPLACE'. – gofr1

+0

* то же самое относится к вашему решению * Нет, предикат ''x [substring ((./ text()) [1], 1,1) =" # "]'' будет фильтровать только те, у которых есть '#' как первый символ. Ну, это будет включать * голый # *, который можно легко решить с помощью len-check. Вы правы со своей второй точкой, но в этом случае один ** должен ** использовать '..., TYPE) .value ('.', 'Nvarchar (max)')', чтобы перекодировать все сущности ... – Shnugo

0

Еще один подход, использующий 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 
+0

Привет, я исправил ненужную запятую и кстати: если вы поместите 'WITH numbers (number) AS SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM master..spt_values)' перед выбором, вы даже не нужна таблица физического номера – Shnugo

+0

@ Шнуго: спасибо за исправление, у меня была таблица чисел, поэтому она использовалась – TheGameiswar

+1

Shure, просто чтобы ваш образец был * автономным * ... – Shnugo