2011-01-23 10 views
8

Mam jakieś niemożliwe żądanie :).SQL - Daj mi 3 trafienia dla każdego typu tylko

Mam tabelę, w której jedna z kolumn ma nazwę type. Chciałbym WYBRAĆ 3 rekordy dla każdego typu w tej kolumnie. Czy to jest możliwe?

Należy również pamiętać, że używam MySQL i Sphinx.

UPDATE: struktura Tabela

id  title  type 
1  AAAA   string1 
2  CCCC   string2 
3  EEEE   string2 
4  DDDD   string2 
5  FFFF   string2 
6  BBBB   string2 
6  BBBB   string2 

Chcę mój powrót jest MySQL (do 3 rekordów dla każdego typu zamówionej z tytułu):

id  title  type 
1  AAAA   string1 
6  BBBB   string2 
2  CCCC   string2 
4  DDDD   string2 
+3

Po pierwsze prawie nic nie jest niemożliwe. Po drugie, dlaczego nie chcesz pokazać swojej struktury tabeli i tego, co wypróbowałeś do tej pory. – ircmaxell

Odpowiedz

12
select id, title, type 
from (select id, title, type, 
       @num := if(@group = type, @num + 1, 1) as row_number, 
       @group := type as dummy 
     from your_table 
     order by type, title) as x 
where row_number <= 3 

(! Używa a different article w tym samym miejscu jak Martin Wickman's answer)

+0

Bardzo, bardzo ładne! – xpepermint

+0

+1 dla stałego zamówienia przez – RichardTheKiwi

0

Wymeldowanie this artykułu. Biorąc pod uwagę:

+--------+------------+-------+ 
| type | variety | price | 
+--------+------------+-------+ 
| apple | gala  | 2.79 | 
| apple | fuji  | 0.24 | 
| apple | limbertwig | 2.87 | 
| orange | valencia | 3.59 | 
| orange | navel  | 9.36 | 
| pear | bradford | 6.05 | 
| pear | bartlett | 2.14 | 
| cherry | bing  | 2.55 | 
| cherry | chelan  | 6.33 | 
+--------+------------+-------+ 

Zapytanie:

select type, variety, price 
from fruits 
where (
    select count(*) from fruits as f 
    where f.type = fruits.type and f.price < fruits.price 
) <= 2; 
+0

To zapytanie wyświetli więzi, więc jeśli 4 owoce mają tę samą cenę, wszystkie są wyświetlane (zamiast 3). Nie było również próby połączenia z tym pytaniem. – RichardTheKiwi

+0

Jeśli sześć odmian jabłek ma tę samą, najniższą cenę, wszystkie sześć zostanie zwrócone. Ale na przykładzie OP myślę, że id jest prawdopodobnie unikalnym identyfikatorem (jeśli, to jest, oba "6" są produkowane w wyniku JOIN) i można użyć kolumny id zamiast kolumny ceny, aby uzyskać gwarantowany prawidłowy wynik. –

2

Gdy stół jest duży i kolekcja jest bardziej nieprzewidywalny, numeracja wierszy należy uporządkować według typu w wewnętrznej kwerendzie, aby zmienne boczne zadziałały.

select id, title, type 
from (select id, title, type, 
     @r := CASE WHEN @g = type THEN @r+1 ELSE 1 END r, 
     @g := type 
     from tbl 
     order by type, title) as x 
where row_number <= 3 
# order by type, title 

Innym sposobem, aby to zrobić bez używania strony dokonujące zmiennych, jeśli nie dwa rekordy są dokładnie takie same na (tytuł, typ, ID), znajduje się poniżej. Używa tylko standardowego SQL SQL ANSI SQL92. Może być wolniejszy niż wyżej.

select A.id, A.title, A.type 
from tbl A 
left join tbl B on 
    A.title = B.title and 
    (A.type < B.type or 
    (A.type = B.type and A.id < A.id)) 
group by A.id, A.title, A.type 
having count(B.title) <= 2 
+0

Tak, zauważyłem to i zrobiłem to, zanim ten został opublikowany. –

2

Jeśli masz indeksu na (type, title) i wiesz możliwe wartości type, wierzę, że dynamiczny SQL jest do zrobienia (na raz) dla uzyskania najlepszej wydajności.

Dla każdej możliwej wartości type dodaj sumę wszystkich i wybierz dla tego określonego typu. Końcowa zapytanie będzie wyglądać następująco zapytania:

(select * from t1 where type = 'string1' order by title limit 3) 
    union all 
(select * from t1 where type = 'string2' order by title limit 3) 
    union all 
(select * from t1 where type = 'string3' order by title limit 3); 

Wykonuje się mniej niż 1 sekundę na stole z 1,000,000 rzędach, podczas gdy inne rozwiązania (Martins & Cyberkiwis) trwa około 11 sekund.

Różnica polega na tym, że powyższa wyszukiwarka ujednolicona może pobrać pierwsze trzy pozycje tytułu dla każdego typu, a następnie zatrzymać, podczas gdy funkcja symulowanej analityki musi przeskanować całą tabelę.

+0

Moja baza danych zawiera 200k rekordów i jest ich ponad 500. Co sugerujesz? – xpepermint

+0

@ photepepter, przejdź do rozwiązania Martins. Po prostu wiedz, że będzie wolniej, gdy dodasz rekordy. W pewnym momencie stanie się szybsze wykonywanie 500 zapytań w pętli. W zależności od konfiguracji może już tak być. Musisz zmierzyć się. – Ronnis

Powiązane problemy