sql >> Base de Datos >  >> RDS >> Mysql

Formulación de subconsultas complejas de MySQL

Estoy de acuerdo con Strawberry sobre el esquema. Podemos discutir ideas para un mejor rendimiento y todo eso. Pero aquí está mi opinión sobre cómo resolver esto después de algunos chats y cambios en la pregunta.

Tenga en cuenta a continuación los cambios de datos para hacer frente a varias condiciones límite que incluyen libros sin imágenes en esa tabla y desempates. Desempates significado usando el max(upvotes) . El OP cambió la pregunta varias veces y agregó una nueva columna en la tabla de imágenes.

La pregunta modificada se convirtió en devolución de 1 fila por libro. Tacha eso, siempre 1 fila por libro aunque no haya imágenes. La información de la imagen a devolver sería la que tenga el máximo de votos a favor.

Mesa de libros

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

Cambios en los datos de la pregunta original.

Principalmente los nuevos upvotes columna.

A continuación se incluye una fila de desempate agregada.

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

Visualización de una tabla derivada

Esto es solo para ayudar a visualizar una parte interna de la consulta final. Demuestra el gotcha para situaciones de desempate, por lo tanto, el rownum variable. Esa variable se restablece a 1 cada vez que bookid cambia de lo contrario se incrementa. Al final (nuestra consulta final) solo queremos rownum=1 filas para que se devuelva un máximo de 1 fila por libro (si corresponde).

Consulta final

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

Resultados

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

El significado de la cross join es simplemente introducir y establecer valores iniciales para 2 variables. Eso es todo.

Los resultados son los diez libros principales en orden descendente de purchasecount con la información de images si existe (de lo contrario NULL ) para la imagen más votada. La imagen seleccionada respeta las reglas de desempate eligiendo la primera como se mencionó anteriormente en la sección Visualización con rownum .

Reflexiones finales

Le dejo al OP encajar en el where apropiado cláusula al final ya que los datos de muestra dados no tenían un nombre de libro útil para buscar. Esa parte es trivial. Ah, y haz algo con el esquema para el gran ancho de tus claves primarias. Pero eso está fuera de tema en este momento.