Mysql
 sql >> Database >  >> RDS >> Mysql

Formulazione di sottoquery complesse MySQL

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.