Jeg er enig med Strawberry om skemaet. Vi kan diskutere ideer til bedre ydeevne og alt det der. Men her er mit bud på, hvordan man løser dette efter et par chats og ændringer af spørgsmålet.
Bemærk nedenfor dataændringerne for at håndtere forskellige randbetingelser, som inkluderer bøger uden billeder i den tabel og tie-breaks. Tie-breaks betyder at bruge max(upvotes)
. OP ændrede spørgsmålet et par gange og tilføjede en ny kolonne i billedtabellen.
Ændret spørgsmål blev retur 1 række fabrikat pr. bog. Rids det, altid 1 række pr. bog, selvom der ikke er nogen billeder. Billedinformationen, der skal returneres, ville være den med maks. opstemmer.
Tabel med bøger
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);
Dataændringer fra det oprindelige spørgsmål.
Hovedsageligt de nye upvotes
kolonne.
Nedenstående inkluderer en tie-break række tilføjet.
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);
Visualisering af en afledt tabel
Dette er blot for at hjælpe med at visualisere en indre del af den endelige forespørgsel. Det demonstrerer gotcha for tie-break situationer, således rownum
variabel. Denne variabel nulstilles til 1 hver gang bookid
ændres ellers stiger den. Til sidst (vores sidste forespørgsel) vil vi kun have rownum=1
rækker, så der maksimalt returneres 1 række pr. bog (hvis nogen).
Endelig forespørgsel
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
Resultater
+----+---------------+---------------------+----------+
| 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 |
+----+---------------+---------------------+----------+
Betydningen af cross join
er blot at indføre og indstille startværdier for 2 variable. Det er alt.
Resultaterne er de ti bedste bøger i faldende rækkefølge efter purchasecount
med oplysningerne fra images
hvis den findes (ellers NULL
) for det mest stemte billede. Det valgte billede overholder tie-break reglerne og vælger det første som nævnt ovenfor i visualiseringssektionen med rownum
.
Sidste tanker
Jeg overlader det til OP at kile den passende where
ind klausul i slutningen, da de angivne eksempeldata ikke havde noget brugbart bognavn at søge på. Den del er triviel. Åh, og gør noget ved skemaet for den store bredde af dine primære nøgler. Men det er off-topic i øjeblikket.