Это близко к догадкам, но мой волшебный хрустальный шар (и Мартин Смит) сказал мне, что вы можете искать что-то вроде этого:
DECLARE @mokupPosts TABLE(ID INT IDENTITY, SomePost VARCHAR(250),Tags VARCHAR(250));
INSERT INTO @mokupPosts VALUES
('First post','<matlab><plot><ternary><ternplot>')
,('Second post','<powershell><java><python>')
,('Third post','<image><opencv><image-processing>');
- запрос будет возвращать несколько строк вPost
с каждым токеном отдельно.
SELECT p.*
,B.token.value('text()[1]','varchar(100)') Token
FROM @mokupPosts p
CROSS APPLY(SELECT CAST('<x>' + REPLACE(REPLACE(REPLACE(REPLACE(p.Tags,'><','||'),'<',''),'>',''),'||','</x><x>') + '</x>' AS XML)) A(Casted)
CROSS APPLY A.Casted.nodes('/x') B(token);
Вы можете легко INNER JOIN
сделать это в существующей таблице Tags
непосредственно на токене и выполнить группировку COUNT()
.
Еслитеги могут включать запрещенные символы (например, &, < and >
и многие другие), вы можете использовать дополнительный внутренний SELECT FOR XML PATH('')
, чтобы неявно экранировать их:
SELECT p.*
,B.token.value('text()[1]','varchar(100)') Token
FROM @mokupPosts p
CROSS APPLY(SELECT CAST('<x>' + REPLACE((SELECT REPLACE(REPLACE(REPLACE(p.Tags,'><','||'),'<',''),'>','') AS [*] FOR XML PATH('')),'||','</x><x>') + '</x>' AS XML)) A(Casted)
CROSS APPLY A.Casted.nodes('/x') B(token);
ОБНОВЛЕНИЕ: упрощенный подход
Внимание: Теги не должны содержать символы, запрещенные в именах элементов, например &, < and >
(и многие другие)!
Этот запрос вернет список пустых элементов в формате xml , просто заменив закрывающий >
с />
.Затем запрос будет использовать /*
, чтобы выполнить итерацию всех из них и вернуть их имя с помощью local-name(.)
:
SELECT p.*
,B.token.value('local-name(.)','varchar(100)')AS Token
FROM @mokupPosts p
CROSS APPLY(SELECT CAST(REPLACE(p.Tags,'>','/>') AS XML)) A(Casted)
CROSS APPLY A.Casted.nodes('/*') B(token)
Результат будет таким же, как указано выше ...
ОБНОВЛЕНИЕ 2:Я только что попробовал это здесь
... и это работает: -)