2017-07-21 44 views
5

Mam poniższą tabelę i moim celem jest poszukiwanie klientów, którzy najbardziej przypominają danego klienta, w jaki sposób ocenili niektórych producentów. Ten przykład można znaleźć w tym SQL fiddle.MySQL: Jak zamówić wynik zapytania SQL przez numeryczną różnicę wielu wierszy?

customer manufacturer rating 
A   Manuf_A   8 
A   Manuf_B   3 
B   Manuf_A   4 
B   Manuf_Y   3   
C   Manuf_X   3 
C   Manuf_Y   7 
D   Manuf_A   8 
D   Manuf_B   7 

Przykład:

Chcemy dowiedzieć się, jakie klienci Najlepszy mecz klientów 'A' który ma rating dla dwóch producentów, manuf_A i manuf_B.

Pożądane rezultaty:

customer difference 
D   4   
B   7 
C   11 

Oczekiwany algorytm:

  • Im mniejsza wartość różnicy jest bliżej związana dwaj klienci są
  • Jeśli klient nie udostępniać ocenę producenta dowolnemu klientowi, ich nieistniejący rating powinien wynosić zero. Różnica

B:

abs(A.manuf_A.rating (8) - B.manuf_A.rating(4)) = 4 
abs(A.manuf_B.rating (3) - B.manuf_B.rating(Doesn't exist/0)) = 3 
= 4 + 3 
= 7 

C różnica:

abs(A.manuf_A.rating (8) - C.manuf_A.rating(Doesn't exist/0)) = 8 
abs(A.manuf_B.rating (3) - C.manuf_B.rating(Doesn't exist/0)) = 3 
= 8 + 3 
= 11 

różnica D:

abs(A.manuf_A.rating (8) - D.manuf_A.rating(8)) = 0 
abs(A.manuf_B.rating (3) - D.manuf_A.rating(7)) = 4 
= 0 + 4 
= 4 

Wszelkie porady, w jaki sposób można to zrobić w MySQL będzie dobrze przyjęty wraz z wszelkimi sugestiami dotyczącymi alternatywnego podejścia.

+1

Tylko komentarz: To naprawdę dobrze napisane pytanie. Podałeś przykład SQL Fiddle (który działa). Wyjaśniłeś wyraźnie problem. Jako bonus jest to interesujący problem. –

+0

[Odległość euklidesowa] (https://en.wikipedia.org/wiki/Euclidean_distance) może być lepszym rozwiązaniem. –

+0

@PaulSpiegel. . . Jeśli to sprawia, że ​​czujesz się lepiej, nazywa się to odległością Manhattanu i jest całkowicie uzasadnione dla takiego problemu. –

Odpowiedz

2

Oto jedno podejście. Wygeneruj wszystkie wiersze dla klientów i producentów, którzy ocenili "A". Następnie użyj left join, aby znaleźć te ocenione przez danego klienta. Reszta jest po prostu arytmetyczna:

select c.customer, 
     sum(abs(am.rating - coalesce(cd.rating, 0))) as similarity 
from (select cd.manufacturer, cd.rating 
     from centraldatabase cd 
     where cd.customer = 'A' 
    ) am cross join 
    customers c left join 
    centraldatabase cd 
    on cd.manufacturer = am.manufacturer and cd.customer = c.customer 
group by c.customer 
order by similarity asc; 

Oto SQLFiddle. Uwaga: Nie wiem, czy dobrze jest stworzyć własny schemat w Fiddle SQL.

+0

Wielkie dzięki, za szybką reakcję i ponieważ działa to świetnie! Względnie nowy w MySQL, więc z przyjemnością poświęcę trochę czasu na przetrawienie tego, co się tutaj dzieje :) Ach tak, to stworzenie schematu wyjaśniłoby kilka dziwactw! – mgibson