Ik ben het met Strawberry eens over het schema. We kunnen ideeën bespreken voor betere prestaties en zo. Maar hier is mijn mening over hoe dit op te lossen na een paar chats en wijzigingen in de vraag.
Noteer hieronder de gegevenswijzigingen om met verschillende randvoorwaarden om te gaan, waaronder boeken zonder afbeeldingen in die tabel en tiebreaks. Tie-breaks betekenis met behulp van de max(upvotes)
. De OP heeft de vraag een paar keer gewijzigd en een nieuwe kolom toegevoegd aan de afbeeldingentabel.
Gewijzigde vraag werd retour 1 rij maken per boek. Kras dat, altijd 1 rij per boek, ook als er geen afbeeldingen zijn. De afbeeldingsinformatie die moet worden geretourneerd, is degene met maximale stemmen.
Boekentabel
create table books
( id int primary key,
name varchar(1000),
releasedate date,
purchasecount int
) ENGINE=InnoDB;
insert into books values(1,"fool","1963-12-18",456);
insert into books values(2,"foo","1933-12-18",11);
insert into books values(3,"fooherty","1943-12-18",77);
insert into books values(4,"eoo","1953-12-18",678);
insert into books values(5,"fooe","1973-12-18",459);
insert into books values(6,"qoo","1983-12-18",500);
Gegevenswijzigingen van oorspronkelijke vraag.
Voornamelijk de nieuwe upvotes
kolom.
Het onderstaande bevat een tiebreak-rij toegevoegd.
create table images
( bookid int,
poster varchar(150) primary key,
bucketid int,
upvotes int -- a new column introduced by OP
) ENGINE=InnoDB;
insert into images values (1,"xxx",12,27);
insert into images values (5,"pqr",11,0);
insert into images values (5,"swt",11,100);
insert into images values (2,"yyy",77,65);
insert into images values (1,"qwe",111,69);
insert into images values (1,"blah_blah_tie_break",111,69);
insert into images values (3,"qwqqe",14,81);
insert into images values (1,"qqawe",8,45);
insert into images values (2,"z",81,79);
Visualisatie van een afgeleide tabel
Dit is alleen om te helpen bij het visualiseren van een binnenste deel van de uiteindelijke vraag. Het demonstreert de gotcha voor tie-break-situaties, dus het rownum
variabel. Die variabele wordt elke keer dat de bookid
. op 1 wordt gezet verandert, anders neemt het toe. Uiteindelijk (onze laatste vraag) willen we alleen rownum=1
rijen zodat er maximaal 1 rij wordt geretourneerd per boek (indien aanwezig).
Laatste zoekopdracht
select b.id,b.purchasecount,xDerivedImages2.poster,xDerivedImages2.bucketid
from books b
left join
( select i.bookid,i.poster,i.bucketid,i.upvotes,
@rn := if(@lastbookid = i.bookid, @rn + 1, 1) as rownum,
@lastbookid := i.bookid as dummy
from
( select bookid,max(upvotes) as maxup
from images
group by bookid
) xDerivedImages
join images i
on i.bookid=xDerivedImages.bookid and i.upvotes=xDerivedImages.maxup
cross join (select @rn:=0,@lastbookid:=-1) params
order by i.bookid
) xDerivedImages2
on xDerivedImages2.bookid=b.id and xDerivedImages2.rownum=1
order by b.purchasecount desc
limit 10
Resultaten
+----+---------------+---------------------+----------+
| id | purchasecount | poster | bucketid |
+----+---------------+---------------------+----------+
| 4 | 678 | NULL | NULL |
| 6 | 500 | NULL | NULL |
| 5 | 459 | swt | 11 |
| 1 | 456 | blah_blah_tie_break | 111 |
| 3 | 77 | qwqqe | 14 |
| 2 | 11 | z | 81 |
+----+---------------+---------------------+----------+
De betekenis van de cross join
is slechts het invoeren en instellen van startwaarden voor 2 variabelen. Dat is alles.
De resultaten zijn de top tien boeken in aflopende volgorde van purchasecount
met de info van images
als het bestaat (anders NULL
) voor de afbeelding met de meeste stemmen. De geselecteerde afbeelding voldoet aan de tie-break-regels en kiest de eerste zoals hierboven vermeld in de sectie Visualisatie met rownum
.
Laatste gedachten
Ik laat het aan de OP over om in de juiste where
te wiggen clausule aan het einde omdat de gegeven voorbeeldgegevens geen bruikbare boeknaam hadden om op te zoeken. Dat deel is triviaal. Oh, en doe iets aan het schema voor de grote breedte van je primaire sleutels. Maar dat is momenteel off-topic.