Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> similar_text w MySQL
#luq
post
Post #1





Grupa: Zarejestrowani
Postów: 589
Pomógł: 91
Dołączył: 22.05.2008
Skąd: Gliwice

Ostrzeżenie: (0%)
-----


Potrzebuje na poziomie bazy wyciągnąć rekordy w których jedno z pól jest zbliżone w 90% do podanego ciągu. Tak w PHP jest funckja similar_text jednak to powinno się robić na poziomie bazy. Chodzi o coś takiego:

  1. SELECT foo.id FROM foo WHERE SIMILAR( foo.name, 'jakis string' ) > 0.9


tyle, że takiej funkcji w MySQL nie ma winksmiley.jpg Da się to w ogóle zrobić na MySQL`u?

Na forum znalazłem identyczny temat http://forum.php.pl/index.php?showtopic=70797 jednak nie rozwiązany...


--------------------
Moja gra - scraby.io
Go to the top of the page
+Quote Post
wookieb
post
Post #2





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




W mysql jest wyszukiwanie pełnotekstowe (FULLTEXT) dla tabel na silniku MyIsam. Na silniku InnoDb powinieneś użyć sphinxa.
Zapomnij o soundex, służy do czegoś innego. Levensthein jest czymś podobnym ale potrzebuje funkcji składowanej http://codejanitor.com/wp/2007/02/10/leven...tored-function/

Podpowiedź aby zainstalować procedurę.
  1. DELIMITER |;
  2. [KOD PROCEDURY]
  3.  
  4. DELIMITER ;


--------------------
Go to the top of the page
+Quote Post
#luq
post
Post #3





Grupa: Zarejestrowani
Postów: 589
Pomógł: 91
Dołączył: 22.05.2008
Skąd: Gliwice

Ostrzeżenie: (0%)
-----


Super. Dzięki!

Btw. rozumiem, że to inne algorytmy są, bo dla
  1. similar_text( 'abrakadabra', 'kadabra', $procent );
  2. echo $procent;


dostaje: 77,(7)

natomiast dla:
  1. SELECT LEVENSHTEIN_RATIO( 'abrakadabra', 'kadabra' );


dostaje: 64


--------------------
Moja gra - scraby.io
Go to the top of the page
+Quote Post
wookieb
post
Post #4





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Jest to różnica algorytmów.
similar_text korzysta z algorytma Olivera , drugi Levenshteina
Wyniki, które podałeś są oczywiste.

Może powiedz co chcesz uzyskać to dobierzemy coś dla Ciebie.


--------------------
Go to the top of the page
+Quote Post
#luq
post
Post #5





Grupa: Zarejestrowani
Postów: 589
Pomógł: 91
Dołączył: 22.05.2008
Skąd: Gliwice

Ostrzeżenie: (0%)
-----


W sumie to dla mnie chyba bez różnicy który algorytm, wystarczy skalibrować przy ilu % otrzymuje dane które są na tyle podobne, że możliwe, że to literówka.


--------------------
Moja gra - scraby.io
Go to the top of the page
+Quote Post
wookieb
post
Post #6





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Przy prostych literówkach lepiej nie porównywać procentowo tylko po prostu liczbowo.
Odległość levenstheina mówi ile zmian musisz dokonać aby jedno słowo zamienić w drugie. Więc myślę że 3 (max 4) są w zupełności zadowalające.


--------------------
Go to the top of the page
+Quote Post
#luq
post
Post #7





Grupa: Zarejestrowani
Postów: 589
Pomógł: 91
Dołączył: 22.05.2008
Skąd: Gliwice

Ostrzeżenie: (0%)
-----


Sprawdzę. Na pewno będzie to szybsze smile.gif

Nie będę zakładać nowego tematu, ale mam kolejne zapytanie:
  1. SELECT id, name, LEVENSHTEIN_RATIO( name, '/*tu mam zmienna*/' ) AS similar FROM foo WHERE LEVENSHTEIN_RATIO( name, '/*tu mam zmienna*/' ) >= 90 GROUP BY id ORDER BY similar DESC


i ogólnie chodzi mi o to, że hm... funkcja LEVENSHTEIN_RATIO jest wykonywana 2 razy tak? Czy nie wiem jest ten wynik jakoś cachowany w bazie? Jeśli nie to jak zrobić tak aby nie liczyć tego 2 razy bo przy kilku tys. rekordów to troszkę trwa. Nie sprawdzałem (jest późno a mnie się oczy kleją) ale podzapytanie dało by chyba radę. Jakieś inne rozwiązanie?


--------------------
Moja gra - scraby.io
Go to the top of the page
+Quote Post
wookieb
post
Post #8





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Szczerze to nie chce mi się teraz kombinować ale wystarczy użyć having albo zmiennej. Co lepiej, niestety za późno by testować smile.gif


--------------------
Go to the top of the page
+Quote Post
#luq
post
Post #9





Grupa: Zarejestrowani
Postów: 589
Pomógł: 91
Dołączył: 22.05.2008
Skąd: Gliwice

Ostrzeżenie: (0%)
-----


Okej to tak, zwykła odległość Levenstheina przy małych stringach powinna być mała.
  1. SELECT authorName FROM `msh_name_author` WHERE LEVENSHTEIN( authorName, 'kant' ) < 4


Dostaje:
Kod
Ray
TEST
kant
kant.


Dla warunku < 3 wyniki są jak dla mnie zadowalające
Kod
kant
kant.


Ale przy długich stringach max 2 zmieny to imho mało, więc chyba zostanę jednak na procentowej wersji.

Użyłem zmiennej i HAVING i nie zauważam zmniejszenia czasu wykonani, może jednak to nie jest liczone 2 razy?
  1. SELECT authorId, authorName, (
  2. @t := LEVENSHTEIN_RATIO( authorName, 'kant' )
  3. ) AS similar
  4. FROM msh_name_author
  5. HAVING similar > 70


Jeszcze jedna sprawa - dla tabelki w której mam ~1200 rekordów to jest strasznie wolne (~7 sec) więc pomyślałem, żeby nie mielić całej tabelki tylko rekordy o inentycznej pierwszej literze, wygląda to tak:
  1. SELECT authorId, authorName, (
  2. @t := LEVENSHTEIN_RATIO( authorName, 'kant' )
  3. ) AS similar
  4.  
  5. FROM (
  6. SELECT authorId, authorName
  7. FROM msh_name_author
  8. WHERE SUBSTRING( authorName, 1, 1 ) = 'k'
  9. ) AS foo
  10. HAVING similar >70

Prawie przy 'k' wykonuje się ~0.2 sec więc jest okej. Przy szukaniu literówek to chyba dobry pomysł bo raczej rzadko robi się literówkę w pierwszym znaku, chyba że ma ktoś inny pomysł?

Ten post edytował #luq 21.05.2010, 09:57:15


--------------------
Moja gra - scraby.io
Go to the top of the page
+Quote Post
wookieb
post
Post #10





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Ten pomysł jest ok, ale stworzyłbym dodatkową kolumne przedstawiajaca ilosc znakow w słowie.
Dzięki temu np jak szukasz słowo "test" to założysz warunek
  1. dlugosc_slowa BETWEEN 2 AND 6
co jeszcze lepiej ograniczy wyniki

Jeżeli chcesz szukać jeszcze inaczej zainteresuj się n-gramami.


--------------------
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 20.08.2025 - 05:24