Piotr Smoleń

Piotr Smoleń Wielofunkcyjny
NetAdmin ;)

Temat: Postgres - patterny ?

Cześć

Mam takie małe zadanie do zrobienia i potrzebuję wyciągnąć pewne dane z bazy.

Konkretnie potrzebuję zrobić takie zapytanie, które wyciągnie mi wszystkie rekordy pasujące do określonego wzorca.
No i nie było by żadnego problemu gdyby nie fakt, że mój wzorzec jest bardziej szczegółowy niż dane w bazie - czyli odwrotnie niż normalnie.

W moim przypadku wzorcem jest konkretna liczba, niech to będzie: 12151 a w bazie mam rekordy z poniższymi przykładowymi wartościami:

121
1
1215
12

Czy macie pomysł, jak temat ugryźć i zrobić (o ile się da) zapytanie, żeby wyciągnął mi najlepiej pasujący rekord ?

Z góry dzięki za pomoc.

konto usunięte

Temat: Postgres - patterny ?

Ale co to ma zwrócić niby? Najlbiższą liczbę? Czy może porównywać chcesz napisy?
Piotr Smoleń

Piotr Smoleń Wielofunkcyjny
NetAdmin ;)

Temat: Postgres - patterny ?

W bazie znajdują się wcześniej zdefiniowane patterny, ich nazwy i inne mniej ważne dane.

Załóżmy że tabela z danymi ma 2 kolumny (dla uproszczenia):

pattern, nazwa

wprowadzam sobie cztery rekordy, jako przykładowe dane:

121, aaa
1, bbb
1215, ccc
12, ddd

Potrzebuję wyciągnąć rekord, który najlepiej pasuje do mojego wzorca - wzorcem jest numer telefonu.

Znam wzorzec, wiem jaki rekord powinien być zwrócony, potrzebuję zrobić odpowiednie zapytanie do tego :)

W tym przypadku mając numer telefonu: 12151, jako najbardziej pasujący rekord, powinno mi zwrócić: 1215, ccc
Mając inny numer telefonu: 12161, najbardziej pasującym rekordem będzie 121, aaa

Czyli trochę odwrotnie niż normalnie, kiedy wzorcem do wyszukiwania jest coś bardziej ogólnego i wyrzuca mi bardziej szczegółowe rzeczy, pasujące do wzorca.

Mam nadzieję, że udało mi się dość jasno to opisać.

Dzięki.
Marcin Miga

Marcin Miga Programista. Po
prostu programista.

konto usunięte

Temat: Postgres - patterny ?

Tutaj masz dostępną w Postgresie funkcję liczącą odległość Levenshtein (też nic innego nie przychodzi mi do głowy).

http://www.postgresql.org/docs/9.1/static/fuzzystrmatc...Ten post został edytowany przez Autora dnia 17.02.15 o godzinie 19:31
Piotr Smoleń

Piotr Smoleń Wielofunkcyjny
NetAdmin ;)

Temat: Postgres - patterny ?

Ok, dzięki za podpowiedź.

Włączyłem sobie to w mojej bazie i robię pewne próby.
Taka myśl mnie naszła, czy nie da się tego prościej - tzn. czy nie dało by się zrobić tego w jakimś perlu...
Może by było łatwiej ?

Jakie jest Wasze zdanie ?

Pozdrawiam

Edit:

levenshtein chyba nie da mi tego, co potrzebuję, bo z prób wychodzi mi, że porównując 123 do 121 oraz 12, dostaję tą samą odległość (1) Ten post został edytowany przez Autora dnia 17.02.15 o godzinie 19:53
Maciej G.

Maciej G. Projektant /
Programista, Famor
S.A.

Temat: Postgres - patterny ?

A gdyby zrobić selecta z like na pattern z coraz mniejszą liczbą znaków wzorca:

Czyli:

Select k1,k2 from tabela where k1 like '12151%';

jeśli powyższe nic nie zwróci to odejmujemy ostatni znak (z patternu) i robimy takie zapytanie:

Select k1,k2 from tabela where k1 like '1215%';

gdzie k1 to kolumna z numerem

a k2 to kolumna z nazwą

i tak do wyczerpania znaków w przekazanym wzorcu (pierwszy wynik zapytania które coś zwróci jest najlepiej dopasowanym).

Takie zapytanie może też zwrócić więcej niż jeden rekord ,wtedy trzeba by dodać drugie kryterium doprecyzowujące, który rekord z tych zwróconych wybrać (lub zwrócić wszystkie).

Można napisać funkcję SQL której jako argument przekazujesz wzorzec (12151 w tym przypadku) i która zwraca wynik najlepiej dopasowanego (w pętelce np.) - nazwę.

Pozdrawiam.Ten post został edytowany przez Autora dnia 17.02.15 o godzinie 20:37

konto usunięte

Temat: Postgres - patterny ?

To może to: http://www.postgresql.org/docs/9.4/static/pgtrgm.html

Zawsze możesz napisać wszystko w perlu. Najlepiej w pl/perlu, co pozwala na ładowanie dowolnych modułów z CPANa.
Marek Kubiś

Marek Kubiś programista c#

Temat: Postgres - patterny ?

Piotr S.:
Taka myśl mnie naszła, czy nie da się tego prościej - tzn. czy nie dało by się zrobić tego w jakimś perlu...
Może by było łatwiej ?
A co ma język do prościej, trudniej kiedy chodzi o metodykę? :-(
Jakie jest Wasze zdanie ?
To zagadnienie typowe dla sztucznej inteligencji, w szczególności rozpoznawania zmiennych lingwistycznych, w szczególności dla algorytmu uczenia się sieci neuronowej.
levenshtein chyba nie da mi tego, co potrzebuję, bo z prób wychodzi mi, że porównując 123 do 121 oraz 12, dostaję tą samą odległość (1)
??? To oczekujesz rozwiązania w jednym kroku? Przecież otrzymany wynik jest prawidłowy. Proszę zapomnieć o klasycznej logice pierwszego rzędu. Wchodzi się na grunt logiki rozmytej gdzie element należy albo do zbioru, albo do jego dopełnienia. Teraz przestrzeń poszukiwania rozwiązania w bazie jest zawężona i można przystąpić do poszukiwania najlepszego wzorca. To bardzo dużo!

Teraz najważniejsze są kryteria akceptacji rozwiązania, a te są podane zbyt ogólnikowo aby wnioskować, jakie powinny być następne kroki. Stosuje się zasadniczo dwa podejścia, zstępujące lub wstępujące. Jak wybrane podejście nie da satysfakcjonującego wyniku wypada przejść na drugie. Wszystko zależy od "pattern maching". Dalszej pomocy proszę szukać w literaturze z zakresu działania systemów ekspertowych

Temat: Postgres - patterny ?

Maciek podał dobre rozwiązanie, które sprawdzi się, o ile danych nie ma "zbyt dużo".
Jest bardzo proste i łatwe do implementacji.

Przykład - wybacz, że w TSQL, ale nie mam pod ręką PG. Zapewne uda Ci się to przetlumaczyć:

--CREATE TABLE Tab(pattern VARCHAR(20), tekst VARCHAR(20))
--CREATE TABLE Wyniki(pattern VARCHAR(20), tekst VARCHAR(20))

--INSERT INTO Tab VALUES('121', 'aaa')
--INSERT INTO Tab VALUES('1', 'bbb')
--INSERT INTO Tab VALUES('1215', 'ccc')
--INSERT INTO Tab VALUES('12', 'ddd')

DELETE FROM Wyniki

DECLARE @NrTel VARCHAR(10) = '1218735'

WHILE(LEN(@NrTel) > 0)
BEGIN
print @NrTel

INSERT INTO Wyniki SELECT pattern, tekst FROM Tab WHERE pattern LIKE @NrTel + '%'
IF(@@ROWCOUNT > 0) BREAK;

SET @NrTel = LEFT(@NrTel, LEN(@NrTel)-1)
END;

-- coś musimy wybrać w przypadku większej liczby telefonów. Jeśli może być więcej rekordów - usuń TOP 1
SELECT TOP 1 *
FROM Wyniki
WHERE LEN(pattern) = (SELECT MIN(LEN(pattern)) FROM Wyniki)


Przykłady:

DECLARE @NrTel VARCHAR(10) = '1218735'
pattern tekst
121 aaa

DECLARE @NrTel VARCHAR(10) = '1'
pattern tekst
1 bbb

DECLARE @NrTel VARCHAR(10) = '12000009'
pattern tekst
12 ddd

DECLARE @NrTel VARCHAR(10) = '12159102'
pattern tekst
1215 ccc

DECLARE @NrTel VARCHAR(10) = '999'
--- brak wyników ---
Ten post został edytowany przez Autora dnia 05.03.15 o godzinie 15:12

konto usunięte

Temat: Postgres - patterny ?

Najlepsze rozwiązanie to levenshtein (ale możliwe że wolne).

Zajrzyj tutaj:
http://postgresql.nabble.com/Index-for-Levenshtein-dis...

Temat: Postgres - patterny ?

No właśnie Piotr napisał, że ta metryka nie spełniła jego oczekiwań. Jest masa innych metryk, ale prosty, podany niżej algorytm w SQL działa poprawnie..

konto usunięte

Temat: Postgres - patterny ?

Zainteresuj się jeszcze algorytmami oraz strukturami danych typowymi dla problemu spell-checking:

https://nullwords.wordpress.com/2013/03/13/the-bk-tree-...

Co do sieci neuronowej to nie bardzo widzę, jak mogłaby w tym przypadku pomóc, bez żmudnego procesu nauki...

Natomiast gdy już będziesz miał metrykę, to szybkim algorytmem wyszukiwania k najbliższych sąsiadów jest k nearest neighbors zaimplementowany na drzewach typu kd-tree. Mam taki kod, ale w C++, nie w SQLu.Ten post został edytowany przez Autora dnia 21.04.15 o godzinie 18:30

Temat: Postgres - patterny ?

To też jest rozwiązanie. Tak, jak w SQL Serverze można podpiąć własne funkje napisane w .NET, w Oraclu - w Javie, tak w PG da się podpiąć DLLkę napisaną w C/C++

konto usunięte

Temat: Postgres - patterny ?

Adrian O.:
To też jest rozwiązanie. Tak, jak w SQL Serverze można podpiąć własne funkje napisane w .NET, w Oraclu - w Javie, tak w PG da się podpiąć DLLkę napisaną w C/C++

Można też zainstalować sobie pythonowe scikit i napisać procedurkę w plpythonu, która z tego skorzysta.



Wyślij zaproszenie do