sql >> Databáze >  >> RDS >> Mysql

Formulace komplexního poddotazu MySQL

Souhlasím s Strawberry ohledně schématu. Můžeme diskutovat o nápadech na lepší výkon a tak. Ale tady je můj názor na to, jak to vyřešit po několika chatech a změnách v otázce.

Všimněte si níže uvedených změn dat, které se týkají různých hraničních podmínek, které zahrnují knihy bez obrázků v této tabulce a tie-breaky. Tie-break znamená použití max(upvotes) . OP několikrát změnil otázku a přidal nový sloupec do tabulky obrázků.

Upravená otázka se změnila na návrat 1 řádek značky na knihu. Seškrábněte to, vždy 1 řádek na knihu, i když tam nejsou žádné obrázky. Informace o obrázku, které se mají vrátit, budou ty s maximálním počtem hlasů pro.

Tabulka knih

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

Změny dat oproti původní otázce.

Hlavně nové upvotes sloupec.

Níže je přidána řada tie-breaku.

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

Vizualizace odvozené tabulky

To je jen pro pomoc při vizualizaci vnitřní části konečného dotazu. To demonstruje gotcha pro tie-break situace, tedy rownum variabilní. Tato proměnná je resetována na 1 pokaždé, když bookid změní se jinak se zvýší. Nakonec (náš poslední dotaz) chceme pouze rownum=1 řádků tak, aby byl vrácen max. 1 řádek na knihu (pokud existuje).

Konečný dotaz

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

Výsledky

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

Význam cross join je pouze zavést a nastavit počáteční hodnoty pro 2 proměnné. To je vše.

Výsledky jsou prvních deset knih v sestupném pořadí podle purchasecount s informacemi z images pokud existuje (jinak NULL ) pro obrázek s nejvyšším počtem hlasů. Vybraný obrázek dodržuje pravidla tie-breaku, která vybírá první, jak je uvedeno výše v sekci Vizualizace s rownum .

Poslední myšlenky

Nechávám na OP, aby zaklínil příslušné where klauzule na konci, protože uvedená ukázková data neobsahovala žádný užitečný název knihy, ve kterém by se dalo hledat. Ta část je triviální. Jo a udělejte něco se schématem pro velkou šířku vašich primárních klíčů. Ale to je v tuto chvíli mimo téma.




  1. Chyba analýzy:chyba syntaxe, neočekávané „“ (T_ENCAPSED_AND_WHITESPACE)

  2. Funguje Dapper na Mono?

  3. SQL dotaz pro získání hodnot sloupců, které odpovídají MAX hodnotě jiného sloupce?

  4. Vygenerujte náhodné datum v Oracle pomocí DBMS_RANDOM