Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [php][mysql] Pobieranie najpopularniejszych tagów z MySQL
Haczyk67
post 5.12.2009, 15:54:19
Post #1





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 15.02.2009

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


Mam tabelę z polami "tag" oraz "produkt". Może się zdarzyć że produkty maja takie same tagi, a więc zawartość pola tag często sie powtarza.

Chciałbym pobrać 5 najpopularniejszych tagów, ale nie chcę pisać 5 osobnych zapytan tylko optymalnie zmiescic sie w jednym.

Na razie mam coś takiego:

  1. SELECT DISTINCT tag FROM tagi LIMIT 5


Jak najlepiej dodać do tego pobieranie ilości wystąpień tagu? No i oczywiście jak ułożyć WHERE żeby pobrało 5 najpopularniejszych?

Ten post edytował Haczyk67 5.12.2009, 15:55:35
Go to the top of the page
+Quote Post
2 Stron V   1 2 >  
Start new topic
Odpowiedzi (1 - 19)
Crozin
post 5.12.2009, 17:39:04
Post #2





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


IMO masz zły projekt bazy danych. Produkty oraz Tagi to raczej relacja n-n, więc powinieneś mieć trzy tabele:
Produkt (id, nazwa)
Tag (id, nazwa)
ProduktTag (id_produkt, id_tag)

A wybranie najpopularniejszych tagów to: COUNT() + GROUP BY + ORDER BY + LIMIT
Go to the top of the page
+Quote Post
Haczyk67
post 5.12.2009, 19:06:39
Post #3





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 15.02.2009

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


Bazy już niestety zmienić nie moge.

Nie wiem czy dobrze Cię zrozumiełem. Sugerujesz że mam:
1) wysłać select COUNT(tag) from (...)
2)w php znaleść najpop. rekordy
3) wysłać zapytanie po 5 top rekordów używając group by ?
Go to the top of the page
+Quote Post
Crozin
post 6.12.2009, 10:00:25
Post #4





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Nie, powinieneś to zrobić bezproblemowo jednym zapytaniem:
1) Wybierasz: tag, COUNT(tag) - ewentualnie inne kolumny. Pamiętaj by dla COUNTa dodać sobie jakiś alias typu: cnt
2) Grupujesz wyniki wg kolumny tag
3) Sortujesz po wyniku COUNTa - czyli po wspomnianym aliasie cnt
4) Ograniczasz wyniki do 5-ciu
Go to the top of the page
+Quote Post
Haczyk67
post 8.12.2009, 21:26:37
Post #5





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 15.02.2009

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


Chyba jednak przebuduje baze.

Ale to co podałeś id_produkt, id_tag <----- aktualnie mam coś takiego tylko zamiast id tagu mam nazwę tagu

Czyli to samo co napisałem na początku.
Go to the top of the page
+Quote Post
Crozin
post 8.12.2009, 22:36:22
Post #6





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Mając nazwę zamiast ID strasznie sobie komplikujesz życie, bo powtarzasz masę danych w bazie.

  1. SELECT tag, COUNT(tag) AS tag_count FROM tbl_name GROUP BY tag ORDER BY tag_count DESC LIMIT 5;
Go to the top of the page
+Quote Post
Haczyk67
post 9.12.2009, 15:20:33
Post #7





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 15.02.2009

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


Ale jeden tag może pasować do wielu różnych produktów a więc jeśli dam ID nic to niezmieni, dalej będę miał masę powtórzeń.
Go to the top of the page
+Quote Post
Crozin
post 9.12.2009, 17:18:11
Post #8





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Tak, ale operowanie na liczbach jest nieporównywalnie lżejsze od męczenia się ze stringami.
Go to the top of the page
+Quote Post
Haczyk67
post 9.12.2009, 17:45:17
Post #9





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 15.02.2009

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


OK, w takim razie powiedz mi ktore rozwiazanie jest lepsze:

1)
Produkt (id, nazwa)
Tag (id, nazwa)
ProduktTag (id_produkt, id_tag) <-- i tu masa duplikatów

czy może

2)
Produkt (id, nazwa, tagi(czyli np. "tag1, tag2"))
Tag (id, nazwa, produkty(czyli np. "produkt1, produkt2")

Aha i mówisz że liczby są lepsze, a więc tag1, tag2 i produkt1, produkt2 to ID
Go to the top of the page
+Quote Post
Crozin
post 9.12.2009, 17:54:26
Post #10





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Jakiekolwiek wyszukiwanie, porównywanie czy łączenie w drugim przypadku będzie katorgą. Poza tym nie chodzi o powtarzanie się jakichkolwiek danych, a o rzeczy typu: nazwa tagu, nazwa produktu itp., ID to co innego.
Go to the top of the page
+Quote Post
thek
post 9.12.2009, 18:11:24
Post #11





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Przy podziale:
Produkt (id, nazwa)
Tag (id, nazwa)
ProduktTag (id_produkt, id_tag)
Nie ma żadnych duplikatów. Dlaczego? Wyjaśnię bo sam tego używam ( w nieco innej wersji ) i napisze JAK używam. Jeśli to UPDATE to wpierw usuwasz wszystkie wpisy w ProduktTag z danym id produktu. Potem robisz z tagów tablice (explode gdzie przecinek to delimiter), trimujesz elementy i robisz array_unique smile.gif Teraz tylko pozostaje stworzenie wpisów w ProdutTag. Jeśli to INSERT nowego produktu to nie usuwasz wcześniej z ProduktTag nic. Kluczem jest tutaj zastosowanie przed zapisem do bazy sprawdzenia czy dany tag już istnieje w bazie. To kwestia zapytania do bazy i później użycia tego co dostałeś i array_diff oraz zapisu nowych tagów do bazy tagow. Sam podobnie robię bez jakichkolwiek dubli w bazie. Kwestia to przemyślany dobrze algorytm.



--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
Haczyk67
post 9.12.2009, 18:17:17
Post #12





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 15.02.2009

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


Ok w takim razie robię pierwszy projekt.

@thek pewnie dobrze mówisz ale niestety nie rozumiem z tego nic ;-)

Aha i jeszcze co do tego zapytania to w pierwqszym projektcie bedzie działać to co podałeś?

Cytat
SELECT tag, COUNT(tag) AS tag_count FROM tbl_name GROUP BY tag ORDER BY tag_count DESC LIMIT 5;


Ten post edytował Haczyk67 9.12.2009, 18:18:53
Go to the top of the page
+Quote Post
thek
post 9.12.2009, 21:13:24
Post #13





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




To może wytłumaczę Ci algorytm i na jego podstawie wyłapiesz co jest grane...
1. Pobierz pole z tagami.
2. Zrób z nich tablicę tagów. (explode)
3. Usuń z tablicy duble. (array_unique)
4. Utwórz zapytanie sprawdzające czy dane tagi są w bazie i zwracające. (zapytanie do tabeli TAG oparte o kilka LIKE 'tag')
5. Zrób z wyników zapytania tablicę. (choćby w pętli)
6. Wykryj różnicę pomiędzy Twoimi tagami a zwróconymi przez bazę. (array_diff)
7. Jeśli są jakieś, to owe "dodatkowe" dodaj do bazy i poznaj ich id_tag. (tu można na kilka sposobów)
8. Jeśli to UPDATE to usuń z ProduktTag wszystkie rekordy tyczące produktu o danym id_produkt. (tu nawet nie ma co się rozpisywać - delete smile.gif )
9. Dodaj do bazy ProduktTag rekordy z danym id_produkt i uzyskanymi id_tagów. (tu zwykły insert)
To cały algorytm. Chyba już prościej się nie da. Następny krok to byłby gotowiec winksmiley.jpg


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
Haczyk67
post 14.12.2009, 20:41:10
Post #14





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 15.02.2009

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


Użycie

Produkt (id, nazwa)
Tag (id, nazwa)
ProduktTag (id_produkt, id_tag) <--- tu znajduje sie troche duplikatów

strasznie wsyzstko komplikuje i powoduje że będę musiał
1) pobrać wszystkie tagi (+distinct)
2) pętlą wykonać x zapytan (count(tag))
3) porownac wszystkie tagi
4) pobrac 5 najpoularniejszych

Nie mogę użyć tego co podałeś
SELECT tag, COUNT(tag) AS tag_count FROM tbl_name GROUP BY tag ORDER BY tag_count DESC LIMIT 5;

Prosze o rozwiązanie jak pobrać 5 tagów bo już przebudowałem bazę tak jak radziłeś i nie wiem jak to rozwikłać mimo paru dni staran.
Go to the top of the page
+Quote Post
Crozin
post 14.12.2009, 21:43:40
Post #15





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Cytat
tu znajduje sie troche duplikatów
Tam nie ma prawa być żadnego duplikatu - powinno Ci wywalić wtedy błąd, bo powinieneś mieć PRIMARYKEY(id_produkt, id_tag).

Dlaczego nie możesz użyć tamtego zapytania? Jaki błąd wywala i jaka jest dokładna treść zapytania?
Go to the top of the page
+Quote Post
thek
post 15.12.2009, 10:23:00
Post #16





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Cytat(Haczyk67 @ 14.12.2009, 20:41:10 ) *
tu znajduje sie troche duplikatów
Tu nie może być żadnego duplikatu. Każda para jest unikalna. Widocznie starych par nie usuwałeś. Patrz na PUNKT 8 z mojego ostatniego posta.
Cytat(Haczyk67 @ 14.12.2009, 20:41:10 ) *
Nie mogę użyć tego co podałeś
SELECT tag, COUNT(tag) AS tag_count FROM tbl_name GROUP BY tag ORDER BY tag_count DESC LIMIT 5;
Więc włącz myślenie. Skoro masz nazwy tabel Produkt, Tag, ProduktTag o podanej strukturze, to zapytanie musisz do tego DOPASOWAĆ
1. Pogrupuj tagi z tabeli złączeniowej ProduktTag po id_tag i zrób count na tym polu.
2. By dodatkowo uzyskać nazwę-słowo. Połącz z tabelą Tag po jego id
3. Pole z nazwą (i ewentualnie id) tagu oraz ich ilość wrzuć do wyświetlanych kolumn.
Jaki efekt?
  1. SELECT t.id, t.nazwa, count(z.id_tag) AS liczba FROM ProduktTag z LEFT JOIN Tag t ON z.id_tag = t.id GROUP BY z.id_tag ORDER BY liczba DESC LIMIT 5


Ten post edytował thek 15.12.2009, 10:23:52


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
Haczyk67
post 15.12.2009, 21:02:54
Post #17





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 15.02.2009

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


Dzięks, już śmiga

Niestety pojawił się kolejny problem. Musze miec ilosć wystapien danego tagu. Jedyne co mi przychodzi do glowy to zapisać wyniki podanego przez was zapytania w tablicy $abcdef[x]['tag_ID']['tag_count'], potem pętlą pobranie nazw tagów o tym ID i dalej niestety nie mam pomysłu jak połączyć te dane.
Go to the top of the page
+Quote Post
thek
post 16.12.2009, 08:54:17
Post #18





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Czy Ty właściwie sprawdziłeś co Ci podałem w wyniku? Zobacz CO Ci zwraca to zapytanie! masz ID tagu, ilość wystąpień i nazwę. Masz wszystkie dane już. Dlatego użyłem LEFT JOIN z tabelą Tag, by ową nazwę wyciągnąć. Zrób sobie to zapytanie w PhpMyAdmin czy czego tam użuywasz i sprawdź dokładnie zamiast bezmyślnie przepisywać smile.gif


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
Crozin
post 16.12.2009, 13:30:30
Post #19





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


btw: nie ma sensu używać LEFT/RIGHT JOIN'a w takich przypadkach (gdy mamy pewność istnienia wszystkich relacji).
Go to the top of the page
+Quote Post
Haczyk67
post 16.12.2009, 15:06:56
Post #20





Grupa: Zarejestrowani
Postów: 56
Pomógł: 0
Dołączył: 15.02.2009

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


Użyłem rozwiazania crozina, tego starego. Nie testowalem Twojego, ale już to naprawiam. Powiedzcie mi tylko czy mam w koncu użyc tego LEFT JOIN czy nie.
Go to the top of the page
+Quote Post

2 Stron V   1 2 >
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 Wersja Lo-Fi Aktualny czas: 24.07.2025 - 21:25