Poslední úpravy - Vyhledat:

SQL

O modelování

Power Designer

Oracle Data Modeler

Krátká videa DM

Zdroje...

edit SideBar

SQL /

Poddotazy

< Agregace pokraèování | SQL postupnì | Dotazy na to co není >

SQL kód nìjakého dotazu mù¾eme uzavøít do závorek a pak zakomponovat do dal¹ího dotazu. Ten vnitøní, zakomponovaný, dotaz je pak poddotazem vnìj¹ího dotazu. Takový kód se interpretuje tak, ¾e výsledek poddotazu stojí na místì, kde je poddotaz ve vnìj¹ím dotazu. Èasto pou¾itím poddotazu ztí¾íme nebo naru¹íme práci optimalizátoru, nìkdy v¹ak poddotaz skuteènì potøebujeme.

Vìt¹inou se jedná o dosti slo¾ité úlohy:


Pøíklad: Pro ka¾dého zákazníka vypi¹te datum a èástku jeho poslední objednávky.

        select LOG, DAT, sum(VCEN) as CASTKA 
        from ZAK left join OBJ o1 on (ZAK.LOG=o1.ZAK) left join POLOZ using (CISO)
        where DAT=(select max(DAT) from OBJ o2 where o2.ZAK=ZAK.LOG)
         or DAT is null
        group by LOG, DAT
        order by 1;
Poddotaz select max(DAT) from OBJ o2 where o2.ZAK=ZAK.LOG najde poslední datum objednávy konkrétního zákazníka. Je to tzv. korelovaný poddotaz, proto¾e ZAK.LOG odkazuje do vnìj¹ího dotazu. Následující formulace v¹ak mù¾e být lépe optimalizována:
        select LOG, MAXDAT, sum(VCEN) as CASTKA 
        from (select ZAK,max(DAT) as MAXDAT from OBJ group by ZAK ) MAXY right join ZAK on (MAXY.ZAK=ZAK.LOG) left join OBJ  on
         (ZAK.LOG=OBJ.ZAK and MAXY.MAXDAT=OBJ.DAT) left join POLOZ using (CISO)
        group by LOG, MAXDAT
        order by 1;
Poddotaz select ZAK,max(DAT) as MAXDAT from OBJ group by ZAK vypoèítává poslední datum objednávky pro ka¾dého zákazníka. (Proto¾e se potøebujeme na výsledek tohoto poddotazu odkazovat v podmínce propojení, musíme ho nìjak pojmenovat – jako v tomto pøípadì MAXY.) Zde ji¾ nemáme korelovaný poddotaz, tak¾e nenutíme databázový engine provádìt operace v urèitém poøadí, ale volbu necháme na nìm.

Pøíklad: Pro ka¾dé zbo¾í vypoèítejme jeho podíl na celkové tr¾bì v jeho kategorii.

        select KAT, KOD, NAZ, 100*sum(VCEN)/KAT_TRZB as PROCENTNI_PODIL 
        from ZBOZ left join POLOZ using(KOD) left join
         (select KAT,sum(VCEN) as KAT_TRZB from ZBOZ left join POLOZ using(KOD) group by KAT) using (KAT)
        group by KAT,KOD,NAZ,KAT_TRZB
        order by 1,4 DESC;
Poddotaz select KAT,sum(VCEN) as KAT_TRZB from ZBOZ left join POLOZ using(KOD) group by KAT nejprve pro ka¾dou kategorii, ve které máme nìjaké zbo¾í, vypoèítá celkovou tr¾bu. (Podle synatxe Oracle jsou v¹echna pole v GROUP BY klauzuli takto nutná.)

Pøíklad: Pro ka¾dého zákazníka porovnejte jeho nákup za roky 2008 a 2009.

        select LOG, R2008, R2009, 100*R2008/R2009 as PROCENTNI_PODIL
        from
         (select ZAK, sum(VCEN) as R2008
           from OBJ join POLOZ using (CISO) where extract(year from DAT)=2008 group by ZAK) R08
         right join ZAK on (R08.ZAK=ZAK.LOG)
         left join
         (select ZAK, sum(VCEN) as R2009
           from OBJ join POLOZ using (CISO) where extract(year from DAT)=2009 group by ZAK) R09 on (R09.ZAK=ZAK.LOG);
Kdy¾ potøebujeme porovnat dvì agregace poèítané podle rùzných podmínek, je univerzálním øe¹ením propojení dvou poddotazù.

Bì¾né úlohy lze vìt¹inou øe¹it bez poddotazù. V nìkterých pøípadech se mù¾e zdát formulace s poddotazem pøíjemnìj¹í, ne v¾dy je v¹ak vhodná:

Pøíklad: Vypi¹te názvy zbo¾í z kategorie, v jejím¾ popisu se vyskytuje "minerální".

        select NAZ 
        from ZBOZ
        where KAT=(select KAT from KAT where POPK like '%minerální%');
Tento kód je sice ekvivalentní s
        select NAZ 
        from ZBOZ join KAT using (KAT)
        where POPK like '%minerální%';
ale mnohému se mù¾e zdát první verze pøirozenìj¹í.

V pøedchozím pøíkladu se vyu¾ilo, ¾e pøíslu¹ná kategorie je jen jedna. Pozor v¹ak na následující

Pøíklad: Vypi¹te e-maily zákazníkù, kteøí si nechávají dovézt objednávky rozvozem (DOPR=2) .

        select distinct EMAIL 
        from ZAK
        where LOG in (select ZAK from OBJ where DOPR=2);
Toto není nejlep¹í formulace, v závislsti na pou¾itém optimalizátoru (v systému jiném ne¾ Oracle) mù¾e být znaènì pomalej¹í ne¾:
        select distinct EMAIL 
        from ZAK join OBJ on (LOG=ZAK)
        where DOPR=2;

Zvlá¹tní kapitolu vìnujeme dotazùm, ve kterých hledáme objekty, o kterých v databázi není ¾ádný záznam urèitých vlastností. O tom viz následující>.

< Agregace pokraèování | SQL postupnì | Dotazy na to co není >

Upravit - Historie - Tisk - Poslední úpravy - Vyhledat
Poslední úprava stránky: 17.10.2013, 18:33