Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Wyświetlenie rekordów podobnych - jak?
pitbull82
post
Post #1





Grupa: Zarejestrowani
Postów: 167
Pomógł: 0
Dołączył: 30.04.2004
Skąd: Częstochowa

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


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


--------------------
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 7)
ciekawskiii
post
Post #2





Grupa: Zarejestrowani
Postów: 467
Pomógł: 39
Dołączył: 7.11.2010
Skąd: Raz tu, raz tam

Ostrzeżenie: (30%)
XX---


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


nie wiem czy o to codzilo:P


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





Grupa: Zarejestrowani
Postów: 167
Pomógł: 0
Dołączył: 30.04.2004
Skąd: Częstochowa

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


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)


--------------------
Go to the top of the page
+Quote Post
zegarek84
post
Post #4





Grupa: Zarejestrowani
Postów: 1 332
Pomógł: 294
Dołączył: 12.10.2008
Skąd: Olkusz

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


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"

Ten post edytował zegarek84 9.11.2010, 01:27:18


--------------------
Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.

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





Grupa: Zarejestrowani
Postów: 167
Pomógł: 0
Dołączył: 30.04.2004
Skąd: Częstochowa

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


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



--------------------
Go to the top of the page
+Quote Post
masters1987
post
Post #6





Grupa: Zarejestrowani
Postów: 23
Pomógł: 2
Dołączył: 7.10.2010

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


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.

Ten post edytował masters1987 1.03.2011, 07:58:58
Go to the top of the page
+Quote Post
wookieb
post
Post #7





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




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ąć.


--------------------
Go to the top of the page
+Quote Post
pitbull82
post
Post #8





Grupa: Zarejestrowani
Postów: 167
Pomógł: 0
Dołączył: 30.04.2004
Skąd: Częstochowa

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


Dzięki wookieb - to chyba rzeczywiście załatwi sprawę.


--------------------
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: 19.08.2025 - 18:08