Предложение по алгоритму облака тегов - PullRequest
2 голосов
/ 13 августа 2010

У меня есть таблица MSSQL 2005:

[Companies](
    [CompanyID] [int] IDENTITY(1,1) NOT NULL,
    [Title] [nvarchar](128),
    [Description] [nvarchar](256),
    [Keywords] [nvarchar](256)
)

Я хочу создать облако тегов для этой компании. Но я сохранил все ключевые слова в одном столбце через запятую. Любые предложения о том, как создать облако тегов по наиболее часто используемым ключевым словам. Может быть миллионы компаний, около десяти ключевых слов на компанию.

Спасибо.

Ответы [ 3 ]

4 голосов
/ 13 августа 2010

Шаг 1: разделите ключевые слова в правильное отношение (таблица).

CREATE TABLE Keywords (KeywordID int IDENTITY(1,1) NOT NULL
  , Keyword NVARCHAR(256)
  , constraint KeywordsPK primary key (KeywordID)
  , constraint KeywordsUnique unique (Keyword));

Шаг 2: сопоставьте отношения «многие ко многим» между компаниями и тегами в отдельной таблице, как и все отношения «многие ко многим»:

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));

Шаг 3:Используйте простой запрос GROUP BY, чтобы сгенерировать «облако» (например, под «облаком» подразумеваются самые распространенные 100 тегов):

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;

Шаг 4: кэшируйте результат, так как он редко изменяется ивычисляет дорого.

1 голос
/ 13 августа 2010

И Ремус, и Джо правы, но да, как сказал Джо, если у вас нет выбора, вам придется с этим жить. Я думаю, что могу предложить вам простое решение, используя тип данных XML. Вы уже можете легко просмотреть проанализированный столбец, выполнив этот запрос

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)

теперь, зная, что вы можете это сделать, все, что вам нужно сделать, это сгруппировать их и сосчитать, но вы не можете сгруппировать методы XML, поэтому я предлагаю создать представление запроса выше

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

и подсчитайте это представление

SELECT Keywords, COUNT(*) AS KeyWordCount FROM DissectedKeywords
GROUP BY Keywords
ORDER BY Keywords

В любом случае, вот полная статья -> http://anyrest.wordpress.com/2010/08/13/converting-parsing-delimited-string-column-in-sql-to-rows/

1 голос
/ 13 августа 2010

Я бы предпочел, чтобы ваш дизайн нормализовался как , предложенный Ремусом , но если вы находитесь в точке, где вы не можете изменить свой дизайн ...

Вы можете использовать функцию синтаксического анализа (пример, который я буду использовать, взят из здесь ), чтобы проанализировать ваши ключевые слова и сосчитать их.

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
...