Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: określona liczba rekordów z określonej liczby kategorii - jak?
Forum PHP.pl > Forum > Bazy danych > MySQL
adalgrim
Witam,

Mam takie pytanko. Czy istnieje możliwość wybrania jednym zapytaniem SQL określonej liczby (przyjmijmy 5) rekordów z tabeli z jednoczesnym uwzględnieniem, że wyciągamy po równo rekordów z określonej liczby kategorii (przyjmijmy 3).

W dużym uproszczeniu: chciałbym jednym zapytaniem wyciągnąć po 5 rekordów z każdej z 3 kategorii.

Definicja tabel jest tu w zasadzie nie istotna, można przyjąć: id, category_id, name
i dajmy na to kilka wpisów:

1, 1, testowo
2, 1, drugi wpis
3, 1, trzeci wpis
4, 2, druga kategoria
5, 2, druga kategoria 2
6, 2, ostatni wpis z tej kategorii
7, 3, trzecia kategoria
8, 3, trzecia kategoria 2
9, 3, wpis z trzeciej kategorii

Z góry dziękuje za pomoc smile.gif
ayeo
Witam!

Oczywiście, że można biggrin.gif Tylko musisz skorzystać z niedocenianego GROUP + HAVING winksmiley.jpg

Pozdrawiam!

edit: Chyba się trochę zagalopowałem :/
adalgrim
Hmm tylko, że GROUP BY w tym wypadku sprawi iż dostanę po 1 rekordzie z każdej kategorii, a ja bym chciał dostać powiedzmy najnowszych 5 (ORDER BY id DESC)
ayeo
Tak, tak - zagalopowałem się winksmiley.jpg Nie daje mi spokoju Twoje pytanie. Jak coś wymyślę to dam znać smile.gif
adalgrim
właśnie mi też nie daje spokoju...

Wiem, że można by to zrobić xx zapytaniami, gdzie xx określa liczbę wybieranych kategorii, ale to trochę pójście na łatwiznę i nie jestem przekonany, czy z punktu optymalizacji liczby wysyłanych zapytań jest to rozwiązanie najlepsze smile.gif

Zastanawiam się jak to robią duże portale typu onet, wp. Mają przecież podział na kategorie na stronie głównej z określoną liczbą wpisów, ale czy wysyłają 5x zapytanie z limitem?
ayeo
Oni cachują to na pewno więc to inna para kaloszy. Wiem, że da się to zrobić jednym zapytaniem. Wiem nawet kto wie jak, ale nikogo nie ma akurat biggrin.gif Jak co to dam odpowiedź w temacie winksmiley.jpg
ziqzaq
Witam.
Znalazłem takie rozwiązanie:
  1. SELECT id, cat_id, name
  2. FROM t1 WHERE (
  3. SELECT count(*) FROM t1 AS tt
  4. WHERE tt.cat_id = t1.cat_id AND tt.id < t1.id
  5. ) <= 4 ORDER BY cat_id;

Nie wiem tylko czy jest optymalne. winksmiley.jpg
adalgrim
Nie głupie smile.gif jednak nie do końca rozwiązuje mój problem. Faktycznie najnowsze/najstarsze w ten sposób można wyciągnąć. A jak wyciągnąć losowe rekordy z tych kategorii?

Myślałem czy nie można by tego rozwiązać jednym prostym zapytaniem, które faktycznie zmniejszy obciążenie serwera smile.gif
Bo mając np. 3 kategorie, z których chcę wyciągnąć po 5 rekordów to 3 proste zapytania mogą działać szybciej niż ten COUNT w podzapytaniu...
A może się mylę?smile.gif

--edit:

Znalazłem rozwiązanie, ale otrzymuję jedynie 1 rekord dla każdej kategorii. Jak to zrobić, by dostać powiedzmy 3 rekordy?

  1. SELECT (SELECT v2.name FROM v_home v2 WHERE v.cat = v2.cat ORDER BY RAND() LIMIT 1 ) AS nazwa FROM v_home v GROUP BY v.cat;


jeszcze inne rozwiązanie - niestety na sztywno i nie jestem pewny co do szybkości działania, może się ktoś wypowiedzieć?

  1. (SELECT * FROM v_home WHERE cat = 1 ORDER BY RAND() LIMIT 5 )
  2. UNION
  3. (SELECT * FROM v_home WHERE cat = 2 ORDER BY RAND() LIMIT 5 )
  4. UNION
  5. (SELECT * FROM v_home WHERE cat = 3 ORDER BY RAND() LIMIT 5 );


ewentualnie jak to samo napisać bez unii?
dotangelo
Myślę, że musiałbyś pokombinować z Sejf-Joinami. Myślę, że będzie to wydajniejsze niż UNION'y. Jak znajdę chwilę w tygodniu i nikt nie odpowie, to pokombinuje jak napisać takie zapytanie.
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.