Mysql
 sql >> Base de données >  >> RDS >> Mysql

Formulation de sous-requêtes complexes MySQL

Je suis d'accord avec Strawberry sur le schéma. Nous pouvons discuter d'idées pour de meilleures performances et tout ça. Mais voici mon point de vue sur la façon de résoudre ce problème après quelques discussions et modifications de la question.

Notez ci-dessous les changements de données pour traiter diverses conditions aux limites, notamment les livres sans images dans ce tableau et les tie-breaks. Signification des tie-breaks en utilisant le max(upvotes) . L'OP a modifié la question plusieurs fois et a ajouté une nouvelle colonne dans le tableau des images.

La question modifiée est devenue une marque de retour d'une ligne par livre. Grattez cela, toujours 1 ligne par livre même s'il n'y a pas d'images. Les informations d'image à renvoyer seraient celles avec le maximum de votes positifs.

Tableau des livres

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);

Modifications des données par rapport à la question d'origine.

Principalement les nouveaux upvotes colonne.

Ci-dessous, une ligne de tie-break a été ajoutée.

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);

Visualisation d'une table dérivée

C'est juste pour aider à visualiser une partie interne de la requête finale. Il démontre le piège des situations de tie-break, donc le rownum variable. Cette variable est réinitialisée à 1 à chaque fois que le bookid change sinon il s'incrémente. À la fin (notre dernière requête), nous ne voulons que rownum=1 lignes de sorte qu'une ligne maximum soit renvoyée par livre (le cas échéant).

Requête 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

Résultats

+----+---------------+---------------------+----------+
| 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 |
+----+---------------+---------------------+----------+

La signification de la cross join est simplement d'introduire et de définir des valeurs de départ pour 2 variables. C'est tout.

Les résultats sont les dix meilleurs livres par ordre décroissant de purchasecount avec les informations des images s'il existe (sinon NULL ) pour l'image la plus votée. L'image sélectionnée respecte les règles de tie-break en choisissant la première comme mentionné ci-dessus dans la section Visualisation avec rownum .

Réflexions finales

Je laisse à l'OP le soin de caler le where approprié clause à la fin car les exemples de données fournis n'avaient pas de nom de livre utile pour effectuer une recherche. Cette partie est triviale. Oh, et faites quelque chose à propos du schéma pour la grande largeur de vos clés primaires. Mais c'est hors sujet pour le moment.