代码之家  ›  专栏  ›  技术社区  ›  HasanG Joe Dabones

标签云算法建议

  •  2
  • HasanG Joe Dabones  · 技术社区  · 14 年前

    我有一个MSSQL2005表:

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

    我想为这些公司生成一个标签云。但我已经将所有关键字保存在一列中,用逗号分隔。关于如何通过使用最多的关键字生成标签云的任何建议。可能有数以百万计的公司,每个公司大约有十个关键词。

    谢谢您。

    3 回复  |  直到 14 年前
        1
  •  4
  •   Remus Rusanu    14 年前

    步骤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:使用简单的分组查询生成“cloud”(例如,以“cloud”表示最常见的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:缓存结果,因为它很少更改,并且计算成本很高。

        2
  •  1
  •   Community Mike Causer    7 年前

    我宁愿把你的设计标准化为 suggested by Remus 但是如果你的设计不能改变…

    您可以使用解析函数(我将使用的示例来自 here )解析关键字并对其进行计数。

    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
    
        3
  •  1
  •   Raymund    14 年前

    雷姆斯和乔都是对的,但是是的,就像乔说的那样,如果你没有选择,那么你就必须忍受。我想我可以通过使用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/