sql >> Database >  >> RDS >> Mysql

Patroon vergeleken met mysql tussen twee tabellenkolom

Twee vragen - zijn de beschrijvingen standaard (beschrijvingen veranderen niet) of zijn ze ingevoerd door een gebruiker? Als ze standaard zijn, voeg dan een kolom toe die een geheel getal is en vergelijk deze kolom.

Als het door de gebruiker is ingevoerd, is uw werk ingewikkelder omdat u op zoek bent naar iets dat meer vaag is. Ik heb een bi-gram-zoekalgoritme gebruikt om de overeenkomst tussen twee strings te rangschikken, maar dit kan niet rechtstreeks in mySQL worden gedaan.

In plaats van een vage zoekopdracht, zou je LIKE kunnen gebruiken, maar de efficiëntie is beperkt tot het doen van tabelscans als je uiteindelijk de '%' aan het begin van de zoekterm plaatst. Het houdt ook in dat je een overeenkomst kunt krijgen op het substringgedeelte dat je kiest, wat betekent dat je de substring van tevoren moet weten.

Ik zou graag meer uitleg geven zodra ik weet wat je probeert te doen.

EDIT1:Ok, gezien je uitwerking, moet je een zoekopdracht in vage stijl uitvoeren, zoals ik al zei. Ik gebruik een bi-grammethode, waarbij elke invoer door de gebruiker wordt genomen en in stukken van 2 of 3 tekens wordt gesplitst. Ik sla vervolgens elk van deze chunks op in een andere tabel, waarbij elk item teruggaat naar de eigenlijke beschrijving.

Voorbeeld:

Description1:"Een snelle run vooruit"Description2:"Een korte run vooruit"

Als je elk in 2 char brokken breekt - 'A', 'f', 'fa', 'as','st'.....

Dan kun je het aantal van 2 char chunks vergelijken die overeenkomen met beide strings en een "score" krijgen die nauwkeurigheid of gelijkenis tussen de twee aangeeft.

Aangezien ik niet weet welke ontwikkeltaal je gebruikt, laat ik de implementatie achterwege, maar dit is iets dat niet expliciet in mySQL moet worden gedaan.

Of het luie alternatief zou zijn om een ​​cloud-zoekservice zoals Amazon te gebruiken die zoeken biedt op basis van termen die je het geeft ... niet zeker of ze je toestaan ​​​​om voortdurend nieuwe beschrijvingen toe te voegen om te overwegen, en afhankelijk van je toepassing, is het kan een beetje duur zijn (IMHO).

R

Voor een ander SO-bericht over de bigram-implementatie - zie deze SO bigram / fuzzy search

--- Update per vraagsteller uitwerking---

Ten eerste ga ik ervan uit dat je de theorie hebt gelezen over de links die ik heb gegeven.. ten tweede, ik zal proberen het zo DB-agnostisch mogelijk te houden, omdat het geen mySQL nodig heeft (hoewel ik het gebruik, en het werkt meer dan prima)

Ok, dus de bigram-methode werkt alleen goed bij het maken/vergelijken van in-memory arrays als de mogelijke overeenkomsten relatief klein zijn, anders lijdt het vrij snel onder een tabelscanprestatie zoals een mysql-tabel zonder indexen. U gaat dus de sterke punten van de database gebruiken om het indexeren voor u te doen.

Wat u nodig heeft, is één tabel waarin de door de gebruiker ingevoerde "termen" of tekst die u wilt vergelijken, kunnen worden weergegeven. De eenvoudigste vorm is een tabel met twee kolommen, één is een uniek auto-increment integer dat zal worden geïndexeerd, we noemen hieronder hd_id, de tweede is een varchar(255) als de strings vrij kort zijn, of TEXT als ze dat kunnen lang worden - je kunt dit noemen wat je wilt.

Vervolgens moet u een andere tabel maken die ten minste DRIE kolommen heeft - één voor de referentiekolom terug naar de automatisch oplopende kolom van de andere tabel (we noemen dit hieronder hd_id), de tweede zou een varchar() van zeg maximaal 5 tekens (dit zal je bigram-chunks bevatten) die we hieronder "bigram" zullen noemen, en de derde een automatisch oplopende kolom met de naam b_id hieronder. Deze tabel bevat alle bigrams voor de invoer van elke gebruiker en is gekoppeld aan de algemene invoer. U wilt de varchar-kolom alleen indexeren (of eerst in volgorde in een samengestelde index).

Elke keer dat een gebruiker een term invoert die u wilt zoeken, moet u de term in de eerste tabel invoeren, de term vervolgens ontleden in bigrams en elk blok in de tweede tabel invoeren met de verwijzing terug naar de algemene term in de eerste tafel om de relatie te voltooien. Op deze manier doe je de dissectie in PHP, maar laat je mySQL of welke database dan ook de indexoptimalisatie voor je doen. Het kan in de bigram-fase helpen om het aantal in tabel 1 gemaakte bigrams op te slaan voor de rekenfase. Hieronder staat wat code in PHP om je een idee te geven hoe je de bigrams kunt maken:

// 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;
}    

Maak je geen zorgen over spaties in de tekenreeksen - ze zijn eigenlijk heel handig als je nadenkt over fuzzy zoeken.

Dus je krijgt de bigrams, voert ze in een tabel in, gekoppeld aan de algemene tekst in tabel 1 via en geïndexeerde kolom...wat nu?

Wanneer u nu zoekt naar een term zoals "Mijn favoriete term om naar te zoeken", kunt u de php-functie gebruiken om er een reeks bigrams van te maken. Je gebruikt dit dan om het IN (..) deel van een SQL-statement op je bigram-tabel(2) te maken. Hieronder is een voorbeeld:

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

Ik heb de $sqlstr als een PHP-stringreferentie achtergelaten - je zou dit zelf kunnen construeren als een door komma's gescheiden lijst van de bigram-functie met behulp van implode of wat dan ook op de array die wordt geretourneerd door get_bigrams of parametriseren als je wilt.

Indien correct uitgevoerd, retourneert de bovenstaande zoekopdracht de meest overeenkomende fuzzy-zoektermen, afhankelijk van de lengte van de bigram die u hebt gekozen. De lengte die u kiest, heeft een relatieve werkzaamheid op basis van uw verwachte lengte van de totale zoekreeksen.

Ten slotte - de bovenstaande query geeft alleen een fuzzy match-rang. U kunt spelen met en verbeteren door niet alleen overeenkomsten te vergelijken, maar overeenkomsten met het totale aantal bigrams, wat zal helpen om lange zoekreeksen te de-biasen in vergelijking met korte reeksen. Ik ben hier gestopt omdat het op dit moment veel toepassingsspecifieker wordt.

Ik hoop dat dit helpt!

R




  1. mysql-communityserver versus mysql-installatieprogramma

  2. Hoe id van ingevoegde rij ophalen bij gebruik van upsert met WITH-clausule in Posgres 9.5?

  3. Foutcode 1292 Mysql DateTime

  4. UTF-8 met mysql en php in freebsd Zweedse tekens (åäö)