Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Formulação de subconsulta complexa do MySQL


Concordo com Strawberry sobre o esquema. Podemos discutir ideias para um melhor desempenho e tudo mais. Mas aqui está minha opinião sobre como resolver isso depois de alguns bate-papos e alterações na pergunta.

Observe abaixo as alterações de dados para lidar com várias condições de limite que incluem livros sem imagens nessa tabela e desempates. Significado de tie-breaks usando o max(upvotes) . O OP mudou a pergunta algumas vezes e adicionou uma nova coluna na tabela de imagens.

A pergunta modificada tornou-se return 1 linha make por livro. Raspe isso, sempre 1 linha por livro, mesmo que não haja imagens. A informação da imagem a ser retornada seria aquela com o máximo de votos positivos.

Tabela de livros

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

Mudanças de dados da pergunta original.


Principalmente os novos upvotes coluna.

O abaixo inclui uma linha de desempate adicionada.
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);

Visualização de uma tabela derivada


Isso é apenas para ajudar a visualizar uma parte interna da consulta final. Ele demonstra a pegadinha para situações de desempate, assim o rownum variável. Essa variável é redefinida para 1 cada vez que o bookid muda, caso contrário, ele incrementa. No final (nossa consulta final) queremos apenas rownum=1 linhas para que no máximo 1 linha seja retornada por livro (se houver).


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

O significado da cross join é meramente introduzir e definir valores iniciais para 2 variáveis. Isso é tudo.

Os resultados são os dez principais livros em ordem decrescente de purchasecount com as informações de images se existir (caso contrário NULL ) para a imagem mais votada. A imagem selecionada respeita as regras de desempate escolhendo a primeira conforme mencionado acima na seção Visualização com rownum .

Considerações finais


Deixo para o OP inserir o where apropriado cláusula no final, pois os dados de amostra fornecidos não tinham um nome de livro útil para pesquisar. Essa parte é trivial. Ah, e faça algo sobre o esquema para a grande largura de suas chaves primárias. Mas isso é off-topic no momento.