Sugestão para um algoritmo de nuvem de tags
-
28-09-2019 - |
Pergunta
Eu tenho uma tabela MSSQL 2005:
[Companies](
[CompanyID] [int] IDENTITY(1,1) NOT NULL,
[Title] [nvarchar](128),
[Description] [nvarchar](256),
[Keywords] [nvarchar](256)
)
Quero gerar uma nuvem de tags para essas empresas. Mas eu salvei todas as palavras -chave em uma coluna separada por vírgulas. Quaisquer sugestões de como gerar o Tag Cloud pelas palavras -chave mais usadas. Pode haver milhões de empresas aproximadamente dez palavras -chave por empresa.
Obrigada.
Solução
Etapa 1: Separe as palavras -chave em uma relação adequada (tabela).
CREATE TABLE Keywords (KeywordID int IDENTITY(1,1) NOT NULL
, Keyword NVARCHAR(256)
, constraint KeywordsPK primary key (KeywordID)
, constraint KeywordsUnique unique (Keyword));
Etapa 2: Mapeie a relação muitos para muitos entre empresas e tags em uma tabela separada, como todas as relações muitas para muitas:
CREATE TABLE CompanyKeywords (
CompanyID int not null
, KeywordID int not null
, constraint CompanyKeywords primary key (KeywordID, CompanyID)
, constraint CompanyKeyword_FK_Companies
foreign key (CompanyID)
references Companies(CompanyID)
, constraint CompanyKeyword_FK_Keywords
foreign key (KeywordID)
references Keywords (KeywordID));
Etapa 3: use um grupo simples por consulta para gerar a 'nuvem' (por exemplo, levar a 'nuvem' para significar as 100 tags mais comuns):
with cte as (
SELECT TOP 100 KeywordID, count(*) as Count
FROM CompanyKeywords
group by KeywordID
order by count(*) desc)
select k.Keyword, c.Count
from cte c
join Keyword k on c.KeywordID = k.KeywordID;
Etapa 4: cache o resultado à medida que ele raramente muda e calcula de forma dispensada.
Outras dicas
Eu prefiro ver seu design normalizado como sugerido por Remus, mas se você estiver em um ponto em que não pode mudar seu design ...
Você pode usar uma função de análise (o exemplo que eu usarei é retirado de aqui), para analisar suas palavras -chave e contá -las.
CREATE FUNCTION [dbo].[fnParseStringTSQL] (@string NVARCHAR(MAX),@separator NCHAR(1))
RETURNS @parsedString TABLE (string NVARCHAR(MAX))
AS
BEGIN
DECLARE @position int
SET @position = 1
SET @string = @string + @separator
WHILE charindex(@separator,@string,@position) <> 0
BEGIN
INSERT into @parsedString
SELECT substring(@string, @position, charindex(@separator,@string,@position) - @position)
SET @position = charindex(@separator,@string,@position) + 1
END
RETURN
END
go
create table MyTest (
id int identity,
keywords nvarchar(256)
)
insert into MyTest
(keywords)
select 'sql server,oracle,db2'
union
select 'sql server,oracle'
union
select 'sql server'
select k.string, COUNT(*) as count
from MyTest mt
cross apply dbo.fnParseStringTSQL(mt.keywords,',') k
group by k.string
order by count desc
drop function dbo.fnParseStringTSQL
drop table MyTest
Remus e Joe estão corretos, mas sim como o que Joe disse se você não tem uma escolha, então precisa conviver com isso. Acho que posso oferecer uma solução fácil usando um tipo de dados XML. Você já pode visualizar facilmente a coluna analisada fazendo esta consulta
WITH myCommonTblExp AS (
SELECT CompanyID,
CAST('<I>' + REPLACE(Keywords, ',', '</I><I>') + '</I>' AS XML) AS Keywords
FROM Companies
)
SELECT CompanyID, RTRIM(LTRIM(ExtractedCompanyCode.X.value('.', 'VARCHAR(256)'))) AS Keywords
FROM myCommonTblExp
CROSS APPLY Keywords.nodes('//I') ExtractedCompanyCode(X)
Agora, sabendo que você pode fazer isso, tudo o que você precisa fazer é agrupá -los e contar, mas você não pode agrupar os métodos XML, então minha sugestão é criar uma visão da consulta acima
CREATE VIEW [dbo].[DissectedKeywords]
AS
WITH myCommonTblExp AS (
SELECT
CAST('<I>' + REPLACE(Keywords, ',', '</I><I>') + '</I>' AS XML) AS Keywords
FROM Companies
)
SELECT RTRIM(LTRIM(ExtractedCompanyCode.X.value('.', 'VARCHAR(256)'))) AS Keywords
FROM myCommonTblExp
CROSS APPLY Keywords.nodes('//I') ExtractedCompanyCode(X)
GO
e execute sua contagem com essa visão
SELECT Keywords, COUNT(*) AS KeyWordCount FROM DissectedKeywords
GROUP BY Keywords
ORDER BY Keywords
De qualquer forma, aqui está o artigo completo ->http://anyrest.wordpress.com/2010/08/13/converting-parsing-delimited-string-clumn-in-sql-to-rows/