Mysql
 sql >> Database >  >> RDS >> Mysql

Schema di confronto con mysql tra due colonne di tabelle

Due domande:le descrizioni sono standard (le descrizioni non cambiano) o sono state inserite da un utente? Se sono standard, aggiungi una colonna che sia un numero intero ed esegui il confronto su questa colonna.

Se è inserito dall'utente, il tuo lavoro è più complicato perché stai cercando qualcosa che sia una ricerca più sfocata. Ho usato un algoritmo di ricerca a due grammi per classificare la somiglianza tra due stringhe, ma questo non può essere fatto direttamente in MySQL.

Al posto di una ricerca fuzzy, potresti usare LIKE, ma l'efficienza è limitata all'esecuzione di scansioni di tabelle se finisci per inserire '%' all'inizio del termine di ricerca. Inoltre, implica che puoi ottenere una corrispondenza sulla porzione di sottostringa che scegli, il che significa che dovresti conoscere la sottostringa in anticipo.

Sarei felice di approfondire una volta che saprò cosa stai cercando di fare.

EDIT1:Ok, data la tua elaborazione, dovrai fare una ricerca in stile sfocato come ho detto. Uso un metodo bi-gram, che prevede di prendere ogni voce fatta dall'utente e dividerla in blocchi di 2 o 3 caratteri. Quindi memorizzo ciascuno di questi blocchi in un'altra tabella con ogni voce restituita alla descrizione effettiva.

Esempio:

Descrizione1:"Una corsa veloce in avanti"Descrizione2:"Una breve corsa in avanti"

Se dividi ciascuno in 2 blocchi di caratteri:'A', 'f', 'fa', 'as','st'.....

Quindi puoi confrontare il numero di 2 blocchi di caratteri che corrispondono a entrambe le stringhe e ottenere un "punteggio" che connoterà l'accuratezza o la somiglianza tra i due.

Dato che non so quale linguaggio di sviluppo stai usando, lascerò l'implementazione fuori, ma questo è qualcosa che dovrà essere fatto non esplicitamente in MySQL.

Oppure l'alternativa pigra sarebbe quella di utilizzare un servizio di ricerca cloud come quello di Amazon che fornirà la ricerca in base ai termini che gli fornisci ... non sono sicuro che ti consentano di aggiungere continuamente nuove descrizioni da considerare e, a seconda della tua applicazione, può essere un po' costoso (IMHO).

R

Per un altro post SO sull'implementazione del bigram - vedere questo SO bigram / ricerca fuzzy

--- Aggiornamento per elaborazione interrogante---

Innanzitutto, presumo che tu abbia letto la teoria sui collegamenti che ho fornito.. in secondo luogo, cercherò di mantenerlo il più agnostico possibile, poiché non ha bisogno di mySQL (anche se lo uso e funziona più di bene)

Ok, quindi il metodo bigram funziona bene nella creazione/confronto di array in memoria solo se le possibili corrispondenze sono relativamente piccole, altrimenti soffre di prestazioni di scansione della tabella come una tabella mysql senza indici abbastanza rapidamente. Quindi, utilizzerai i punti di forza del database per aiutarti a eseguire l'indicizzazione per te.

Ciò di cui hai bisogno è una tabella per contenere i "termini" inseriti dall'utente o il testo che stai cercando di confrontare. La forma più semplice è una tabella con due colonne, una è un intero univoco con incremento automatico che verrà indicizzato, chiameremo hd_id di seguito, il secondo è un varchar(255) se le stringhe sono piuttosto brevi, o TEXT se possono ottenere long - puoi nominarlo come vuoi.

Quindi, dovrai creare un'altra tabella che abbia almeno TRE colonne:una per la colonna di riferimento sulla colonna auto-incrementata dell'altra tabella (chiameremo questo hd_id di seguito), la seconda sarebbe un varchar() di diciamo 5 caratteri al massimo (questo manterrà i tuoi blocchi bigram) che chiameremo "bigram" di seguito e il terzo una colonna a incremento automatico chiamata b_id di seguito. Questa tabella conterrà tutti i bigram per la voce di ciascun utente e si ricollegherà alla voce complessiva. Ti consigliamo di indicizzare la colonna varchar da sola (o prima in ordine in un indice composto).

Ora, ogni volta che un utente inserisce un termine che vuoi cercare, devi inserire il termine nella prima tabella, quindi sezionare il termine in bigram e inserire ogni pezzo nella seconda tabella usando il riferimento al termine generale nel prima tabella per completare la relazione. In questo modo, stai eseguendo la dissezione in PHP, ma lasciando che MySQL o qualsiasi altro database eseguano l'ottimizzazione dell'indice per te. Può essere utile nella fase di bigram memorizzare il numero di bigram realizzati nella tabella 1 per la fase di calcolo. Di seguito è riportato del codice in PHP per darti un'idea su come creare i bigram:

// split the string into len-character segments and store seperately in array slots
function get_bigrams($theString,$len)   
{
   $s=strtolower($theString);
   $v=array();
   $slength=strlen($s)-($len-1);     // we stop short of $len-1 so we don't make short chunks as we run out of characters

   for($m=0;$m<$slength;$m++)
   {
      $v[]=substr($s,$m,$len);
   }
   return $v;
}    

Non preoccuparti degli spazi nelle stringhe:in realtà sono davvero utili se pensi alla ricerca fuzzy.

Quindi prendi i bigram, li inserisci in una tabella, collegati al testo generale nella tabella 1 tramite e colonna indicizzata... e adesso?

Ora, ogni volta che cerchi un termine come "Il mio termine preferito da cercare", puoi utilizzare la funzione php per trasformarlo in una matrice di bigram. Quindi lo usi per creare la parte IN (..) di un'istruzione SQL sulla tua tabella bigram (2). Di seguito un esempio:

select count(b_id) as matches,a.hd_id,description, from table2 a
inner join table1 b on (a.hd_id=b.hd_id)
where bigram in (" . $sqlstr . ")
group by hd_id order by matches desc limit X

Ho lasciato $sqlstr come riferimento a una stringa PHP:puoi costruirlo tu stesso come un elenco separato da virgole dalla funzione bigram usando implode o qualsiasi altra cosa sull'array restituito da get_bigrams o parametrizza se lo desideri.

Se eseguita correttamente, la query sopra restituisce i termini di ricerca fuzzy più simili a seconda della lunghezza del bigram che hai scelto. La lunghezza che scegli ha un'efficacia relativa basata sulla lunghezza prevista delle stringhe di ricerca complessive.

Infine, la query sopra, fornisce solo un rango di corrispondenza sfocato. Puoi giocare e migliorare confrontando non solo le corrispondenze, ma anche le partite rispetto al conteggio complessivo dei bigram, il che aiuterà a ridurre la distorsione delle stringhe di ricerca lunghe rispetto alle stringhe corte. Mi sono fermato qui perché in questo frangente diventa molto più specifico dell'applicazione.

Spero che questo aiuti!

R