2016-10-31 9 views
8

W SQL Server, jeśli I wykonaj następujące czynności:Dlaczego funkcja Różnica daje różne wyniki przy zmianie kolejności łańcuchów do porównania?

Difference ('Kennady', 'Kary') : I get 2 

Jeśli zrobić:

Difference ('Kary', 'Kennady') : I get 3. 

Myślałem funkcja Różnica patrzy na wartości SOUNDEX pod maską, i daje 0-4 liczba znaków na miejscu jest taka sama.

SELECT SOUNDEX('Kennady') AS [SoundEx Kennady] 
    , SOUNDEX('Kary') AS [SoundEx Kary] 
    , DIFFERENCE ('Kennady', 'Kary') AS [Difference Kennady vs Kary] 
    , DIFFERENCE ('Kary', 'Kennady') AS [Difference Kary vs Kennady]; 
+1

Sprawdziłem, czy to prawda. I że dokumentacja prawie mówi, że kolejność argumentów nie powinna mieć znaczenia. –

+0

Dzięki. To tak bardzo mnie wyrzuca! – Jay

+0

Dodałem pełny przykład problemu. Widzę to samo zachowanie. – UnhandledExcepSean

Odpowiedz

4

To jest ściśle obserwacyjne. documentation jest całkiem jasne:

Liczba całkowita zwracana jest liczba znaków w SOUNDEX wartości że są takie same. Wartość zwracana jest w zakresie od 0 do 4: 0 oznacza słabe lub żadne podobieństwo, a 4 oznacza silne podobieństwo lub o tych samych wartościach.

Zgodnie z tą dokumentacją wartość zwracana nie powinna się różnić w zależności od kolejności argumentów.

Z moich zapytań: "Kennady" -> K530 i "Kary" -> K600. Mają one wspólne dwa znaki, więc wartość powinna być 2.

Teraz zauważam, że "Kenn" -> K500. Obcięcie "Kennady" na długość "Kary" daje wartość "3". Hmmm.

Dlatego uważam, że DIFFERENCE() używa długości pierwszego argumentu do obcięcia drugiego argumentu. To sprawia, że ​​kolejność argumentów jest ważna. Najpierw ustaw dłuższy argument.

Próbowałem tego na innych ciągach. Te same wzory wydają się działać. Nie znalazłem żadnej dokumentacji, która określałaby, że tak właśnie jest.

Przypuszczam, że Microsoft nazwałby to "funkcją", a nie "błędem";).

EDYTOWANIE:

Powyższe spekulacje nie są całkiem poprawne. Rozważmy następujący

  • leepaupauld -> L114
  • Leopold -> L143
  • leepaup -> L110

Jednak

  • różnica (leepaupauld Leopold) = 4 (!)
  • różnica (leopold, leepaupauld) = 3
  • różnica (leepaup Leopold) = 3 (!)
  • różnica (Leopold, leepaup) = 2

The (!) Jest mój osąd, że wynik nie ma sensu w ogóle, biorąc pod uwagę wartości SOUNDEX dla struny.

Problem nie dotyczy długości. Jest to podstawowa metoda, którą @jpw wskazuje w komentarzu. Problem wydaje się być duplikatem pasujących wartości w jednym ciągu. Jednakże, zgodnie z dokumentacją, nie powinny one wielokrotnie pasować do tej samej postaci.

Moja rada: Użyj odległości Levenshteina. To ma sens. Działa lepiej na dłuższych łańcuchach. To jest przy zdrowych zmysłach. Nie jest wbudowany, ale łatwo znaleźć implementację w Internecie dla dowolnej bazy danych.

+0

Szczegółowy opis używanego algorytmu można znaleźć w tym artykule w języku KB: Funkcje [INF: DIFFERENCE() i SOUNDEX() w języku Transact-SQL] (https://support.microsoft.com/en-us/kb/100365) – jpw

0

Odpowiedz na przykładzie. Porównanie "Bathilda" i "Bagshott"

Po pierwsze: Bathilda Soundex B-343, drugie: Bagshot Soundex-B-230 Drugie wyszukiwania w pierwszej. Pierwszy mecz: B; Następne wyszukiwanie rozpoczyna się po B, z 3 Zwrot "2" nie jest zgodny. Drugi mecz to 3 z drugiego meczu, pierwsze 3 z pierwszego. Iteracja rozpoczyna się od 2. Trzecie dopasowanie to 3 z drugiego meczu, drugie 3 z pierwszego. Wynik to 3.

wstecznego - teraz pierwsze jest Bagshot Soundex-B-230, drugie jest: Bathilda Soundex B-343 Pierwszy mecz jest znowu B. iteracja rozpoczyna się od 2. Drugi mecz to pierwszy z 3 sekundy mecze 3 od pierwszego. Koniec kolejnych iteracji, ponieważ 3 na początku jest ostatnią literą.

Objaśnienie: OD https://msdn.microsoft.com/en-us/library/ms188753.aspx: "RÓŻNICE i SOUNDEX są wrażliwe na sortowanie." Oznacza to, że każde wyszukiwanie rozpoczyna się po ostatnim dopasowaniu i przechodzi do ostatniego znaku w sekwencji. Dlatego dwie sekwencje z taką samą liczbą znaków i tymi samymi znakami dają wynik mniejszy niż 4. Na przykład: Różnica dla "Brts" i "Btrs" daje wynik 2.

+0

Zobacz dokumentację, której @jpw zawiera poniżej. Coś jest nie tak, jeśli jedno "3" w jednym kodzie może dopasować dwa "3" w innym kodzie. Zgodnie z dokumentacją nie powinno to mieć miejsca, ponieważ każde kolejne skanowanie rozpoczyna się * po * poprzednim meczu. –

0

Odwołanie do ostatniego postu wyjaśniającego algorytm : https://social.msdn.microsoft.com/Forums/en-US/a6ba987d-6fde-40d3-bcd0-4c7fd3d2e8cf/tsql-difference-function-returns-different-results-for-same-query?forum=transactsql

UWAGA: To wszystko moja opinia na temat tego, co się dzieje.

Zgodnie z tym postem używa parametru FIRST, a następnie przechodzi przez znak po znaku, szukając dopasowań w drugich parametrach.

Jako przykład, moje imię "Vogel" = V240 w SOUNDEX. "Vasquez" = V220.

DIFFERENCE('Vogel','Vasquez') = 3 

Ponieważ sprawdza "V", "2", "4" i "0" i znajduje 3 dopasowania.

Jednakże

DIFFERENCE('Vasquez','Vogel') = 4 

Ponieważ kontrole "V", "2", "2" i "0" i stwierdza 4 wyników.

Wygląda na to, że pierwszy parametr ma soundex z powielonymi cyframi, które mogą powodować nieoczekiwane wyniki.

Powiązane problemy