sql >> Databasteknik >  >> RDS >> Mysql

Mönster som jämförs med mysql mellan två tabellkolumner

Två frågor - är beskrivningarna standard (beskrivningarna ändras inte) eller är de inmatade av en användare? Om de är standard, lägg till en kolumn som är ett heltal och gör en jämförelse på den här kolumnen.

Om det skrivs in av användaren är ditt arbete mer komplicerat eftersom du letar efter något som är mer otydlig sökning. Jag använde en bi-gram sökalgoritm för att rangordna likheter mellan två strängar, men detta kan inte göras direkt i mySQL.

I stället för en suddig sökning kan du använda LIKE, men dess effektivitet är begränsad till att göra tabellskanningar om du slutar med att sätta "%" i början av söktermen. Det innebär också att du kan få en matchning på den delsträngsdel du väljer, vilket innebär att du måste känna till understrängen i förväg.

Jag utvecklar gärna mer när jag vet vad du försöker göra.

EDIT1:Ok, med tanke på din utarbetning, måste du göra en suddig stilsökning som jag nämnde. Jag använder en bi-gram-metod, som går ut på att ta varje inmatning gjord av användaren och dela upp den i bitar med 2 eller 3 tecken. Jag lagrar sedan var och en av dessa bitar i en annan tabell med varje post tillbaka till den faktiska beskrivningen.

Exempel:

Beskrivning1:"En snabb löpning framåt"Beskrivning2:"En kort löpning framåt"

Om du delar upp var och en i två char-bitar - 'A', 'f', 'fa', 'as', 'st'.....

Sedan kan du jämföra antalet 2 char-bitar som matchar båda strängarna och få en "poäng" som kommer att antyda noggrannhet eller likhet mellan de två.

Eftersom jag inte vet vilket utvecklingsspråk du använder, kommer jag att utelämna implementeringen, men detta är något som måste göras inte uttryckligen i mySQL.

Eller det lata alternativet skulle vara att använda en molnsökningstjänst som Amazon har som ger sökning baserat på termer du ger den...inte säker på om de tillåter dig att kontinuerligt lägga till nya beskrivningar att överväga, och beroende på din applikation, det kan vara lite dyrt (IMHO).

R

För ytterligare ett SO-inlägg om bigramimplementeringen - se denna SO bigram / fuzzy sökning

--- Uppdatering per frågeställare---

För det första antar jag att du läser teorin på länkarna jag angav... för det andra ska jag försöka hålla den så DB-agnostisk som möjligt, eftersom den inte behöver mySQL (även om jag använder den, och den fungerar mer än bra)

Ok, så bigrammetoden fungerar ok för att göra/jämföra arrayer i minnet endast om de möjliga matchningarna är relativt små, annars lider den av en tabellskanningsprestanda som en mysql-tabell utan index ganska snabbt. Så du kommer att använda databasens styrkor för att göra indexeringen åt dig.

Vad du behöver är en tabell för att hålla användaren angivna "termer" eller text som du vill jämföra. Den enklaste formen är en tabell med två kolumner, en är ett unikt heltal med automatisk ökning som kommer att indexeras, vi anropar hd_id nedan, den andra är en varchar(255) om strängarna är ganska korta, eller TEXT om de kan bli lång - du kan namnge detta vad du vill.

Sedan måste du skapa en annan tabell som har minst TRE kolumner - en för referenskolumnen tillbaka till den andra tabellens automatiskt inkrementerade kolumn (vi kallar detta hd_id nedan), den andra skulle vara en varchar() av säg högst 5 tecken (detta kommer att hålla dina bigrambitar) som vi kallar "bigram" nedan, och den tredje en automatiskt ökande kolumn som heter b_id nedan. Den här tabellen kommer att innehålla alla bigram för varje användares inlägg och knyta tillbaka till den övergripande posten. Du vill indexera varchar-kolumnen för sig själv (eller först i ordningen i ett sammansatt index).

Nu, varje gång en användare skriver in en term som du vill söka, måste du ange termen i den första tabellen, sedan dissekera termen den i bigram och ange varje bit i den andra tabellen med hjälp av referensen tillbaka till den övergripande termen i första tabellen för att slutföra relationen. På så sätt gör du dissektionen i PHP, men låter mySQL eller vilken databas som helst göra indexoptimeringen åt dig. Det kan hjälpa i bigramfasen att lagra antalet bigram som gjorts i tabell 1 för beräkningsfasen. Nedan finns lite kod i PHP för att ge dig en idé om hur du skapar bigrammen:

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

Oroa dig inte för mellanslag i strängarna - de är faktiskt väldigt användbara om du tänker på otydlig sökning.

Så du får bigrammen, skriv in dem i en tabell, länkade till den övergripande texten i tabell 1 via en indexerad kolumn...vadå nu?

Nu när du söker efter en term som "Min favoritterm att söka efter" - kan du använda php-funktionen för att förvandla den till en rad bigram. Du använder sedan detta för att skapa IN (..) delen av en SQL-sats på din bigramtabell(2). Nedan är ett exempel:

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

Jag har lämnat $sqlstr som en PHP-strängreferens - du kan konstruera denna själv som en kommaseparerad lista från bigramfunktionen med hjälp av implode eller vad som helst i arrayen som returneras från get_bigrams eller parametrisera om du vill också.

Om den görs på rätt sätt, returnerar frågan ovan de mest matchade suddiga söktermerna beroende på längden på det bigram du valde. Längden du väljer har en relativ effekt baserat på din förväntade längd på de övergripande söksträngarna.

Slutligen - frågan ovan ger bara en suddig matchningsrankning. Du kan leka med och förbättra genom att jämföra inte bara matchningar, utan matchningar mot det övergripande antalet bigram, vilket kommer att hjälpa till att avskaffa långa söksträngar jämfört med korta strängar. Jag har slutat här eftersom det vid det här laget blir mycket mer applikationsspecifikt.

Hoppas detta hjälper!

R




  1. Hur man lägger till ett underformulär till ett formulär i Access 2016

  2. MySql:hur man gör underfråga och räknar alla rader där id är detsamma i två tabeller

  3. Konsekutiv PreparedStatement god praxis

  4. SQL Server-fråga för att hitta alla aktuella databasnamn