sql >> Databasteknik >  >> RDS >> Mysql

MySQL komplex subquery formulering

Jag håller med Strawberry om schemat. Vi kan diskutera idéer för bättre prestanda och allt det där. Men här är min syn på hur man löser detta efter några chattar och ändringar i frågan.

Notera nedan dataändringarna för att hantera olika randvillkor som inkluderar böcker utan bilder i den tabellen, och tie-breaks. Tie-breaks betyder att använda max(upvotes) . OP ändrade frågan några gånger och lade till en ny kolumn i bildtabellen.

Ändrad fråga blev retur 1 rad fabrikat per bok. Skrapa det, alltid 1 rad per bok även om det inte finns några bilder. Bildinformationen att returnera skulle vara den med max uppröster.

Böckertabell

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

Dataändringar från den ursprungliga frågan.

Främst de nya upvotes kolumn.

Nedanstående inkluderar en tie-break rad tillagd.

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

Visualisering av en härledd tabell

Detta är bara för att hjälpa till att visualisera en inre del av den slutliga frågan. Det demonstrerar gotcha för tie-break situationer, alltså rownum variabel. Den variabeln återställs till 1 varje gång bookid ändras annars ökar den. I slutändan (vår sista fråga) vill vi bara ha rownum=1 rader så att max 1 rad returneras per bok (om någon).

Slutlig fråga

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

Resultat

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

Betydelsen av cross join är bara att introducera och ställa in startvärden för 2 variabler. Det är allt.

Resultaten är de tio bästa böckerna i fallande ordning efter purchasecount med informationen från images om det finns (annars NULL ) för den mest röstade bilden. Den valda bilden respekterar tie-break regler och väljer den första som nämnts ovan i avsnittet Visualisering med rownum .

Sluta tankar

Jag överlåter till OP att kila in lämplig where klausul i slutet eftersom exempeldatan inte hade något användbart boknamn att söka på. Den delen är trivial. Åh, och gör något åt ​​schemat för den stora bredden på dina primärnycklar. Men det är off-topic för tillfället.




  1. infoga några tupler i tabellen i web2py

  2. Hur man lägger till tid till ett Datetime-värde i MySQL

  3. Django - Hur länkar man till en äldre databas via mellanhand?

  4. Hur man installerar MySQL med phpMyAdmin på Ubuntu 12.04