2010-07-31 13 views
6

Ho una tabella nel mio DB che contiene una colonna di campo di testo libero.Calcola TF-IDF utilizzando Sql

Vorrei sapere la frequenza di ogni parola su tutte le righe, o forse anche calcolare un TF-IDF per tutte le parole, dove i miei documenti sono i valori di quel campo per riga.

È possibile calcolare questo utilizzando una query Sql? se no o c'è un modo più semplice, per favore, potresti indirizzarmi ad esso?

Molte grazie,

Jon

+0

Cosa RDBMS e la versione? –

+0

Microsoft Sql Server 2008 – Jon

risposta

5

In SQL Server 2008 a seconda delle esigenze è possibile applicare l'indicizzazione full text alla colonna quindi interrogare il sys.dm_fts_index_keywords e sys.dm_fts_index_keywords_by_documenttable valued functions per ottenere il conteggio dell'occorrenza.

Edit: In realtà, anche senza la creazione di una persistente indice completo si può ancora sfruttare il parser

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 

Returns

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

Si rock !!! Questa è una soluzione incredibile che mi avrebbe richiesto giorni per trovare. (Ho solo dovuto aggiungere una riga per filtrare i campi con testo null altrimenti restituirebbe un errore "Null o vuoto predicato full-text", la riga che aggiungo era "WHERE tbl1.txt_field! = '" "'") – Jon

+0

Grazie, lo incorporo nella mia risposta. –

2

soluzione per SQL Server 2008:

Ecco la tabella:

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

qui è query 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 

qui è tabella della funzione valutata Fn_Split (@ id int, @separator VARCHAR (32), @String VARCHAR (MAX)) (tratto da 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