0

请帮助我从在 SQL Server 2008 db 上工作的具有 1 亿条记录的表中构建单词对频率表。表看起来像:

Original table 
id |source |comment(255)
-------------------
1     A1     review budget limitation

source 是一些 ID,可能有大约 800 个不同的值。原始表中的源分布是指数级的。这意味着源 A1 的记录数量可能为 2000 万条,而 A500 仅为 10,000 条。

最后我想得到一个忽略单词的单词对频率表:the, and, of, to, a, i, it, in, or, is

我期望它应该如何工作(我在这里可能不是最佳的):

  1. 从原始表中的评论中读取前两个单词,将其放入 FREQUENCY
  2. 阅读接下来的两个单词并输入

频率表

id | word pairs        | source |Frequency
 ---------------------------------------------
1   review budget         A1         1
2   budget limitation     A1         1 
  1. 填写第一条记录的完整评论,例如源 A1
  2. 开始下一条记录并以相同的方式处理它。
  3. 如果它发现频率表中已经存在相同的单词对,并且来源与增加频率相同,如果来源不同 - 使用新来源添加这对。

请帮助我为 SQL Server 提供最佳 sql 脚本?

4

1 回答 1

1

我会在一分钟内解决这个问题(给定时间),但我想提出两个必要条件:

  • 任何需要在 SQL 中快速完成的事情都需要基于集合完成。避免“一次一个”地处理事情。
  • 使用表值函数将评论拆分为单词对表
  • 使用通用表表达式将您的工作分层以保持可读性

使用这三个规则,您可以移动大量数据。在构建了 select 语句之后,只需将其转储到表中即可。

编辑:

CREATE FUNCTION dbo.SplitToPairs(@sText nvarchar(255))
RETURNS @Pairs TABLE (
    Pair nvarchar(255) NOT NULL
)
AS
BEGIN
    SET @sText = LTRIM(RTRIM(@sText));
    DECLARE @Pos1 int = 0
    DECLARE @Pos2 int = CHARINDEX(' ', @sText);
    DECLARE @Pos3 int;
    IF @Pos2 <> 0
    BEGIN
        DECLARE @Word1 nvarchar(255) = SUBSTRING(@sText, @Pos1+1, @Pos2-@Pos1-1);
        WHILE CHARINDEX(N'|' + @Word1 + N'|', N'|the|and|of|to|a|i|it|in|or|is|') <> 0
        BEGIN
            SET @Pos1 = @Pos2;
            SET @Pos3 = CHARINDEX(' ', @sText, @Pos2+1);
            SET @Pos2 = @Pos3;
            SET @Word1 = SUBSTRING(@sText, @Pos1+1, @Pos2-@Pos1-1);
        END
        DECLARE @Word2 nvarchar(255);

        WHILE @Pos2 <> 0
        BEGIN
            SET @Pos3 int = CHARINDEX(' ', @sText, @Pos2+1);
            IF @Pos3 <> 0
            BEGIN
                SET @Word2 = SUBSTRING(@sText, @Pos2+1, @Pos3-@Pos2-1);
                WHILE CHARINDEX(N'|' + @Word2 + N'|', N'|the|and|of|to|a|i|it|in|or|is|') <> 0
                BEGIN
                    SET @Pos1 = @Pos2;
                    SET @Pos2 = @Pos3;
                    SET @Word2 = SUBSTRING(sText, @Pos2+1, @Pos2-@Pos1-1);
                END
                INSERT @Pairs (Pair) VALUES (@Word1 + N' ' + @Word2)
            END

            SET @Pos1 = @Pos2;
            SET @Pos2 = @Pos3;
            SET @Word1 = @Word2;
        END
    END
    -- Note: if only one word in text, no insert happens
    RETURN @Pairs
END

然后,使用它来构建一个选择

SELECT I.Source, P.Pair, COUNT(*) AS Frequency
FROM Information AS I CROSS APPLY dbo.SplitToPairs(i.Comment) AS P
GROUP BY I.Source, P.Pair

我可能会因为一些极端情况而离开,但它应该让你知道我要做什么。它也不认为“word1 word2”和“word2 word1”是相等的。

我把它作为练习留给读者:p

编辑:

在线添加TABLE关键字RETURNS

DECLARE此外,我认为从 SQL 2008 开始的唯一作品中分配一个值..

编辑:

添加RETURN声明

编辑:

根据 AntarticIce 的反馈进行的更改

于 2012-05-30T14:07:04.220 回答