2010-07-31 19 views
6

J'ai une table dans ma base de données contenant une colonne de champ de texte libre. Je voudrais savoir la fréquence de chaque mot apparaît sur toutes les lignes, ou peut-être même calculer un TF-IDF pour tous les mots, où mes documents sont les valeurs de ce champ par ligne.Calculer TF-IDF en utilisant Sql

Est-il possible de calculer cela en utilisant une requête Sql? sinon, ou y a-t-il un moyen plus simple de me diriger vers cette voie?

Merci beaucoup,

Jon

+0

Qu'est-ce SGBDR et la version? –

+0

Microsoft Sql Server 2008 – Jon

Répondre

5

Dans SQL Server 2008 en fonction de vos besoins, vous pouvez appliquer l'indexation en texte intégral à la colonne puis interroger le sys.dm_fts_index_keywords et sys.dm_fts_index_keywords_by_documenttable valued functions pour obtenir le nombre d'occurrences.

Edit: En fait, même sans créer un index de texte intégral persistant vous pouvez toujours tirer parti de l'analyseur

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 

Retours

display_term     Cnt 
------------------------------ ----------- 
the       3 
brown       2 
lorry       2 
sea       2 
+0

Vous rock !!! C'est une solution incroyable qui m'aurait pris des jours pour trouver. (Je devais seulement ajouter une ligne pour filtrer les champs avec du texte nul sinon il retournerait une erreur "Null ou un prédicat plein texte vide", la ligne que j'ajouterais était "WHERE tbl1.txt_field! = '" "'") – Jon

+0

Merci, je vais intégrer cela dans ma réponse. –

2

Solution pour SQL Server 2008:

ici est la table:

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

ici est la requête 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 

Voici fonction table Fn_Split (@id int, @separator VARCHAR (32), @string VARCHAR (MAX)) (prise de here):

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