使用Sql计算TF-IDF

6
我数据库中有一个包含自由文本字段列的表格。
我想知道每个单词在所有行中出现的频率,甚至可以为所有单词计算TF-IDF,其中我的文档是该字段每行的值。
使用Sql查询是否可以计算此内容?如果不行或者有更简单的方法,请指引我。
感谢您,
Jon
2个回答

6
在SQL Server 2008中,根据您的需求,您可以将全文索引应用于列,然后查询sys.dm_fts_index_keywordssys.dm_fts_index_keywords_by_document表值函数以获取出现次数。 编辑:实际上,即使没有创建持久的全文索引,您仍然可以利用解析器。
WITH testTable AS
(
SELECT 1 AS Id, N'how now brown cow' AS txt UNION ALL
SELECT 2, N'she sells sea shells upon the sea shore' UNION ALL
SELECT 3, N'red lorry yellow lorry' UNION ALL
SELECT 4, N'the quick brown fox jumped over the lazy dog'
)

SELECT display_term, COUNT(*) As Cnt
FROM testTable
CROSS APPLY sys.dm_fts_parser('"' + REPLACE(txt,'"','""') + '"', 1033, 0,0)
WHERE TXT IS NOT NULL
GROUP BY display_term
HAVING COUNT(*) > 1
ORDER BY Cnt DESC

返回
display_term                   Cnt
------------------------------ -----------
the                            3
brown                          2
lorry                          2
sea                            2

你真是太棒了!这是一个令人惊叹的解决方案,如果没有你,我可能需要花费数天时间才能找到。我只需要加上一行代码来过滤空文本字段,否则它会返回一个错误“Null or empty full-text predicate”,我所添加的那一行代码是“WHERE tbl1.txt_field != '""'”。 - Jon
谢谢,我会将这个加入到我的回答中。 - Martin Smith

2

SQL Server 2008的解决方案:

以下是表格:

CREATE TABLE MyTable (id INT, txt VARCHAR(MAX));

这里是 SQL 查询:

SELECT sum(case when TSplitted.txt_word = 'searched' then 1 else 0 end) as cnt_searched
     , count(*) as cnt_all
FROM MyTable MYT 
INNER JOIN Fn_Split(MYT.id,' ',MYT.txt) TSplitted on MYT.id=TSplitted.id

这里是表值函数 Fn_Split(@id int, @separator VARCHAR(32), @string VARCHAR(MAX))(摘自这里):

CREATE FUNCTION Fn_Split (@id int, @separator VARCHAR(32), @string VARCHAR(MAX))

RETURNS @t TABLE
    (
        ret_id INT
       ,txt_word VARCHAR(MAX)
    )   
AS
    BEGIN
        DECLARE @xml XML
        SET @XML = N'<root><r>' + REPLACE(@s, @separator, '</r><r>') + '</r></root>'

        INSERT INTO @t(ret_id, val)
        SELECT @id, r.value('.','VARCHAR(5)') as Item
        FROM @xml.nodes('//root/r') AS RECORDS(r)

        RETURN
    END

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接