Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wyświetlenie rekordów podobnych - jak?
Forum PHP.pl > Forum > PHP
pitbull82
Witam

Mam problem, nie bardzo wiem jak go rozwiązać. Mam w bazie użytkowników. Każdy użytkownik powiedzmy że może określić 10 cech - każda z cech ma do 50 opcji np. 1,2,3,4, ... 50. Chciałbym móc wyświetlić użytkowników, którzy mają jak najwięcej takich cech jak ja, najpierw tych którzy mają 10 identycznych, potem 9, potem 8 itd. Pytanie czy da się jakoś sensownie to przechować w tabeli żeby móc sortować w locie w mysqlu tabele czy może trzeba coś bardziej skomplikowanego wymyślić? Macie jakiś pomysł na rozwiązanie tego problemu?

Pozdrawiam
ciekawskiii
wyswietlasz to normalnym zapytaniem tylko na koncu dodajesz
  1. WHERE opcja='$jaka_opcja' LIMIT 10


nie wiem czy o to codzilo:P
pitbull82
Rzecz w tym, że pól w tabeli będzie przykładowo 10 które mają być porównane np. zainteresowanie, rodzina itd. i chodzi o sortowanie od tych, których wartość pól odpowiada naszym jak najbardziej (max 10/10) do tych najmniej (0/10)
zegarek84
niestety nie znamy struktury danych...

poczytaj o ilorazie zbiorów - gdyż to mi tu najbardziej pasuje - a raczej tego prostsza wersja - jak na szybko sprawdziłem w firefoxie na sqlite to poniższe zadziałąło - gdzie nie ma wypełnionych liczbami tabel i przyjete jest, że moga wystąpić powtórzenia - jeśli ich nie będzie nie potrzebny distinct... nie myślałem nad rozwiązaniem bez grupowania:

  1. CREATE TABLE "liczba" ("l" INTEGER NOT NULL );
  2.  
  3. CREATE TABLE "nazwa_liczba" ("n" TEXT NOT NULL , "l" INTEGER NOT NULL );
  4.  
  5. SELECT
  6. n_l.n AS nazwa,
  7. COUNT(n_l.l) AS dopasowan_wszystkich,
  8. COUNT(DISTINCT n_l.l) AS dopasowan_unikalnych,
  9. (SELECT COUNT(DISTINCT l) FROM liczba WHERE l>=2) AS unikalnych_elementow
  10. FROM nazwa_liczba AS n_l
  11. WHERE n_l.l IN (SELECT l FROM liczba WHERE l>=2)
  12. GROUP BY n_l.n HAVING dopasowan_unikalnych=unikalnych_elementow

gdzie jak iloraz sprawdzałem zapytanie typu (SELECT l FROM liczba WHERE l>=2) z tabeli liczba potraktowałem jako "wirtualną tabele" [gdzie w danej grupie zgodnie z ilorazem muszą się zawrzeć wszystkie liczby|wartości danego zbioru] a na Twoje rozwiązanie algorytm ilorazu pasuje pominąć HAVING i dać ORDER BY dopasowan_unikalnych [lub dopasowan_wszystkich jeśli masz unikalne rekordy w danej grupie] - nie wiem na ile pomogłem ale poczytaj o ilorazie zbiorów sql czy jak tam zwał - jakoś w polskim google tak na szybko nie wiele o tym znalazłem...

ps. to o czym wspominam chyba się nazywa dokładniej "dzieleniem relacyjnym"
pitbull82
Powiem szczerze, ze szukałem co nieco, ale nie znalazłem nic ciekawego. Nie wiem poza tym, czy się dobrze zrozumieliśmy, więc teraz wrzucam przykładowy schemat bazy danych

  1. CREATE TABLE `answers` (
  2. `a_id` int(11) NOT NULL AUTO_INCREMENT,
  3. `a_id_user` int(11) NOT NULL,
  4. `answer_1` tinyint(4) NOT NULL,
  5. `answer_2` tinyint(4) NOT NULL,
  6. `answer_3` tinyint(4) NOT NULL,
  7. `answer_4` tinyint(4) NOT NULL,
  8. `answer_5` tinyint(4) NOT NULL,
  9. `answer_6` tinyint(4) NOT NULL,
  10. `answer_7` tinyint(4) NOT NULL,
  11. `answer_8` tinyint(4) NOT NULL,
  12. PRIMARY KEY (`a_id`)
  13. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
  14.  
  15. --
  16. -- Zrzut danych tabeli `answers`
  17. --
  18.  
  19. INSERT INTO `answers` (`a_id`, `a_id_user`, `answer_1`, `answer_2`, `answer_3`, `answer_4`, `answer_5`, `answer_6`, `answer_7`, `answer_8`) VALUES
  20. (1, 1, 1, 2, 3, 4, 3, 2, 1, 1),
  21. (2, 2, 1, 3, 4, 1, 1, 4, 3, 3),
  22. (3, 3, 1, 4, 3, 2, 1, 4, 1, 1),
  23. (4, 4, 2, 3, 4, 3, 2, 1, 1, 1),
  24. (5, 5, 1, 1, 1, 1, 3, 2, 1, 1);


Chciałbym wyświetlić te rekordy, które pola answer_1 ... answer_8 mają jak najbardziej zbliżone do rekordu o danym a_id_user. Patrząc na dane jeśli szukamy rekordów "podobnych" do rekordu użytkownika 1, to użytkownik 2 ma tylko 1 pole podobne (answer_1), użytkownik 3 ma 4 pola podobne (answer_1, answer_3,answer_7,answer_8), użytkownik 4 ma 2 pola podobne (answer_7,answer_8), użytkownik 5 ma 5 pól podobnych (answer_1,answer_5,answer_6,answer_7,answer_8), to chciałbym w rezultacie otrzymać rekordy z danymi (dopasowanie, a_id_user) posortowane względem dopasowania malejąco, czyli w tym przypadku:

5 5
4 3
2 4
1 2

Pytanie - czy jest to wykonalne? Schemat bazy może zostać dowolnie zmieniony, ale powinien zakładać spore obciążenie - w tej przykładowej tabeli rekordów docelowo może być kilkadziesiąt tysięcy

masters1987
Skorzystaj z funkcji agregujących języka SQL, a dokładnie z COUNT, dodatkowo jeśli chcesz żeby dane były posortowane wystarczy skorzystać z funkcji sortujących.
wookieb
Jak już to przeprojektuj tabele na taką strukture
Kod
id_user, nr_answer, answer, weight


A wtedy wyszukujesz tak
  1. SELECT id_user, sum(weight) AS total_weight
  2. FROM tabela WHERE (nr_answer =1 AND answer = "wartosc") OR (nr_answer=2 AND answer = "wartosc2") (.itd)
  3. GROUP BY id_user
  4. ORDER BY total_weight DESC


Indeksy:
INDEX (nr_answer, answer, id_user)
Powinno styknąć.
pitbull82
Dzięki wookieb - to chyba rzeczywiście załatwi sprawę.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.