Sono d'accordo con Strawberry sullo schema. Possiamo discutere idee per prestazioni migliori e tutto il resto. Ma ecco la mia opinione su come risolvere questo problema dopo alcune chat e modifiche alla domanda.
Nota di seguito le modifiche ai dati per gestire varie condizioni al contorno che includono libri senza immagini in quella tabella e tie-break. Tie-break significa usare il max(upvotes)
. L'OP ha cambiato la domanda alcune volte e ha aggiunto una nuova colonna nella tabella delle immagini.
La domanda modificata è diventata restituita 1 riga per libro. Grattalo, sempre 1 riga per libro anche se non ci sono immagini. Le informazioni sull'immagine da restituire sarebbero quelle con voti massimi.
Tavolo libri
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);
Modifiche ai dati rispetto alla domanda originale.
Principalmente i nuovi upvotes
colonna.
Di seguito è inclusa una riga di tie-break aggiunta.
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);
Visualizzazione di una tabella derivata
Questo è solo per aiutare a visualizzare una parte interna della query finale. Dimostra il gotcha per le situazioni di tie-break, quindi il rownum
variabile. Quella variabile viene reimpostata su 1 ogni volta che viene visualizzato bookid
cambia altrimenti aumenta. Alla fine (la nostra domanda finale) vogliamo solo rownum=1
righe in modo che venga restituita al massimo 1 riga per libro (se presente).
Richiesta finale
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
Risultati
+----+---------------+---------------------+----------+
| 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 |
+----+---------------+---------------------+----------+
Il significato del cross join
consiste semplicemente nell'introdurre e impostare i valori iniziali per 2 variabili. Questo è tutto.
I risultati sono i primi dieci libri in ordine decrescente di purchasecount
con le informazioni da images
se esiste (altrimenti NULL
) per l'immagine più votata. L'immagine selezionata rispetta le regole del tie-break scegliendo la prima come menzionato sopra nella sezione Visualizzazione con rownum
.
Pensieri finali
Lascio all'OP di incunearsi nel where
appropriato clausola alla fine poiché i dati di esempio forniti non avevano un nome di libro utile su cui cercare. Quella parte è banale. Oh, e fai qualcosa per lo schema per la grande larghezza delle tue chiavi primarie. Ma questo è fuori tema al momento.