sql >> Databáze >  >> RDS >> Mysql

Vzor porovnání s mysql mezi dvěma sloupci tabulek

Dvě otázky - jsou popisy standardní (popisy se nemění) nebo je zadává uživatel? Pokud jsou standardní, přidejte sloupec, který je celočíselný, a proveďte srovnání v tomto sloupci.

Pokud jej zadá uživatel, je vaše práce složitější, protože hledáte něco, co je více rozmazané. Použil jsem bigramový vyhledávací algoritmus k hodnocení podobnosti mezi dvěma řetězci, ale to nelze provést přímo v mySQL.

Místo fuzzy vyhledávání můžete použít LIKE, ale jeho účinnost je omezena na skenování tabulek, pokud na začátek hledaného výrazu vložíte '%'. Také to znamená, že můžete získat shodu na části podřetězce, kterou si vyberete, což znamená, že byste museli znát podřetězec předem.

Až budu vědět, o co se snažíte, rád to upřesním.

EDIT1:Dobře, vzhledem k vašemu rozpracování budete muset provést vyhledávání ve fuzzy stylu, jak jsem zmínil. Používám bi-gramovou metodu, která zahrnuje každý záznam vytvořený uživatelem a jeho rozdělení na části po 2 nebo 3 znacích. Každý z těchto bloků pak uložím do jiné tabulky, přičemž každý záznam se vrátí ke skutečnému popisu.

Příklad:

Popis1:"Rychlý běh vpřed"Popis2:"Krátký běh vpřed"

Pokud každý rozdělíte na 2 části znaků - 'A', 'f', 'fa', 'as','st'.....

Poté můžete porovnat počet 2 char chunků, které odpovídají oběma řetězcům, a získat "skóre", které bude znamenat přesnost nebo podobnost mezi těmito dvěma.

Vzhledem k tomu, že nevím, jaký vývojový jazyk používáte, vynechám implementaci, ale toto je něco, co bude potřeba udělat ne explicitně v mySQL.

Nebo by línou alternativou bylo použít službu cloudového vyhledávání, jako je Amazon, která bude poskytovat vyhledávání na základě výrazů, které jí zadáte...nejsem si jistý, zda vám umožňují neustále přidávat nové popisy, které je třeba zvážit, a v závislosti na vaší aplikaci to může být trochu nákladné (IMHO).

R

Další příspěvek SO o implementaci bigramu – viz tento SO bigram / fuzzy vyhledávání

--- Aktualizace podle rozpracování tazatele ---

Za prvé, předpokládám, že jste si přečetli teorii na odkazech, které jsem uvedl. Zadruhé se ji pokusím udržet co nejvíce agnostickou k DB, protože nepotřebuje mySQL (ačkoli ji používám a funguje více než dobře)

Dobře, takže metoda bigramu funguje dobře při vytváření/porovnávání polí v paměti pouze v případě, že možné shody jsou relativně malé, jinak trpí poměrně rychle výkonem skenování tabulky jako tabulka mysql bez indexů. Takže využijete silné stránky databáze, aby vám pomohly s indexováním.

Potřebuješ jednu tabulku, která bude obsahovat uživatelem zadané „termíny“ nebo text, který chceš porovnat. Nejjednodušší formou je tabulka se dvěma sloupci, jeden je jedinečné celé číslo s automatickým přírůstkem, které bude indexováno, níže budeme volat hd_id, druhým je varchar(255), pokud jsou řetězce velmi krátké, nebo TEXT, pokud mohou. dlouho - můžete si to pojmenovat, jak chcete.

Potom budete muset vytvořit další tabulku, která bude mít alespoň TŘI sloupce – jeden pro referenční sloupec zpět do automaticky inkrementovaného sloupce druhé tabulky (níže to budeme nazývat hd_id), druhý by byl varchar() z řekněme maximálně 5 znaků (to bude obsahovat vaše kousky bigramu), které budeme níže nazývat „bigram“, a třetí automaticky se zvyšující sloupec s názvem b_id níže. Tato tabulka bude obsahovat všechny bigramy pro každý záznam uživatele a naváže zpět na celkový záznam. Sloupec varchar budete chtít indexovat samostatně (nebo jako první v pořadí ve složeném indexu).

Nyní, pokaždé, když uživatel zadá výraz, který chcete vyhledat, musíte zadat výraz do první tabulky, poté jej rozdělit na bigramy a zadat každý kus do druhé tabulky pomocí odkazu zpět na celkový výraz v první tabulka k dokončení vztahu. Tímto způsobem provádíte pitvu v PHP, ale necháte mySQL nebo jinou databázi, aby za vás provedla optimalizaci indexu. Ve fázi bigramu může pomoci uložení počtu bigramů vytvořených v tabulce 1 pro fázi výpočtu. Níže je nějaký kód v PHP, který vám poskytne představu, jak vytvořit bigramy:

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

Nedělejte si starosti s mezerami v řetězcích – jsou skutečně užitečné, pokud uvažujete o fuzzy vyhledávání.

Takže získáte bigramy, zadáte je do tabulky, propojíte s celkovým textem v tabulce 1 pomocí a indexovaným sloupcem... co teď?

Nyní, kdykoli budete hledat výraz, jako je „Můj oblíbený výraz k hledání“ – můžete použít funkci php a změnit jej na pole bigramů. To pak použijete k vytvoření IN (..) části SQL příkazu ve vaší tabulce bigram(2). Níže je uveden příklad:

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

$sqlstr jsem ponechal jako odkaz na řetězec PHP - můžete si to vytvořit sami jako seznam oddělený čárkami z funkce bigram pomocí implode nebo čehokoli na poli vráceném z get_bigrams nebo parametrizovat, pokud chcete.

Pokud je proveden správně, výše uvedený dotaz vrátí nejpřesněji odpovídající fuzzy hledané výrazy v závislosti na délce zvoleného bigramu. Délka, kterou zvolíte, má relativní účinnost založenou na vaší očekávané délce celkových vyhledávacích řetězců.

A konečně – výše uvedený dotaz dává pouze fuzzy hodnocení shody. Můžete si hrát a vylepšovat porovnáním nejen shod, ale i shod s celkovým počtem bigramů, což vám pomůže odstranit zkreslení dlouhých vyhledávacích řetězců ve srovnání s krátkými řetězci. Zde jsem se zastavil, protože v tomto okamžiku se to stává mnohem konkrétnější pro aplikaci.

Doufám, že to pomůže!

R




  1. Optimalizace Oracle CONNECT BY při použití s ​​klauzulí WHERE

  2. Porovnání řádků v tabulce pro rozdíly mezi poli

  3. Termín syntaxe SQL pro 'WHERE (sloupec1, sloupec2) <(hodnota1, hodnota2)'

  4. Booleovský dotaz na pole se sqlalchemy