< Poddotazy | SQL postupně | UNION dotazy >
I informace, že záznamy s nějakými vlastnostmi v databázi nejsou, je užitečná. Například se můžeme ptát, jestli někdy došlo ke zlevnění nějakého zboží: ptáme se, zda existují v tabulce POLOZ dva různé záznamy se stejným kódem zboží, druhý s číslem objednávky pozdějším než v prvním záznamu, a s VCEN/MNOZ menším.
Příklad: Existuje dvojice objednávek stejného zboží, první dříve než druhá, s jednotkovou cenou menší v pozdější objednávce?
select PRV.CISO,DRU.CISO,KOD
from POLOZ PRV join POLOZ DRU using (KOD)
where PRV.CISO<DRU.CISO
and PRV.VCEN/PRV.MNOZ>DRU.VCEN/DRU.MNOZ; |
Negativní odpověď nám říká, že ke zlevnění asi nikdy nedošlo, alespoň co se týče uskutečněných objednávek. |
| Typický případ je, že hledáme exempláře nějakého typu, pro něž neexistuje v databázi související záznam nějakých vlastností. Například se ptáme, zda existuje zboží, jež nebylo nikdy objednáno, a případně jaké je to zboží. Množství následujících příkladů vám poskytne návod: |
Příklad: Které zboží nebylo objednáno v žádné objednávce?
select KOD, NAZ
from ZBOZ left join POLOZ using (KOD)
where CISO is null; |
Nebo jinak: |
select KOD, NAZ
from ZBOZ
where KOD not in (select KOD from POLOZ); |
Nebo: |
select KOD, NAZ
from ZBOZ
where not exists (select * from POLOZ where POLOZ.KOD=ZBOZ.KOD); |
Která z předchozích formulací je nejlepší? Odpověď závisí na možnostech optimalizátoru, v ideálním případě jsou stejné. První formulce však poskytuje nejlepší možnosti optimalizace, lze ji tedy doporučit. Zato poslední, s korelovaným poddotazem, nutí databázový engine vykonávat operace v určitém pořadí, tedy jsou v tomto případě možnosti optimalizace nejhorší. Podobně je tomu s dalšími příklady:
Příklad: Které zboží nebylo objednáno v roce 2009?
select ZBOZ.KOD, NAZ
from ZBOZ left join (POLOZ join OBJ using (CISO) ) on (POLOZ.KOD=ZBOZ.KOD and extract(year from DAT)=2009)
where CISO is null; |
Nebo jinak: |
select KOD, NAZ
from ZBOZ
where KOD not in (select KOD from POLOZ join OBJ using (CISO) where extract(year from DAT)=2009); |
Nebo: |
select KOD, NAZ
from ZBOZ
where not exists (select * from POLOZ join OBJ using (CISO) where ZBOZ.KOD=POLOZ.KOD and extract(year from DAT)=2009); |
Příklad: Který zákazník nemá žádnou objednávku?
select LOG
from ZAK left join OBJ on (LOG=ZAK)
where CISO is null; |
Nebo jinak: |
select LOG
from ZAK
where LOG not in (select ZAK from OBJ); |
Nebo: |
select KOD, NAZ
from ZAK
where not exists (select * from OBJ where ZAK=LOG); |
Příklad: Který zákazník nemá žádnou objednávku do osobního převzetí?
select LOG
from ZAK left join OBJ on (LOG=ZAK and DOPR=1)
where CISO is null; |
Nebo jinak: |
select LOG
from ZAK
where LOG not in (select ZAK from OBJ where DOPR=1); |
Nebo: |
select KOD, NAZ
from ZAK
where not exists (select * from OBJ where ZAK=LOG and DOPR=1); |
Příklad: Která kategorie namá žádné podkategorie?
select NAD.KAT
from KAT NAD left join KAT POD on (NAD.KAT=POD.NADR)
where POD.KAT is null; |
Nebo jinak: |
select KAT
from KAT
where KAT not in (select NADR from KAT where NADR is not null); |
Narozdíl od předchozích příkladů, zde připadá do úvahy NULL hodnota v porovnávaném sloupci (NADR). Další možnost: |
select KAT
from KAT NAD
where not exists (select * from KAT POD where NAD.KAT=POD.NADR); |
Příklad: Ve které kategorii není žádné zboží?
select KAT
from KAT left join ZBOZ using (KAT)
where KOD is null; |
Nebo jinak: |
select KAT
from KAT
where KAT not in (select KAT from ZBOZ); |
Nebo: |
select KAT.KAT
from KAT
where not exists (select * from ZBOZ where ZBOZ.KAT=KAT.KAT); |
Příklad: Ve které kategorii není žádné aktivní zboží?
select KAT.KAT
from KAT left join ZBOZ on (KAT.KAT=ZBOZ.KAT and AKTI=0)
where KOD is null; |
Nebo jinak: |
select KAT.KAT
from KAT
where KAT not in (select KAT from ZBOZ where AKTI=0); |
Nebo: |
select KAT.KAT
from KAT
where not exists (select * from ZBOZ where ZBOZ.KAT=KAT.KAT and AKTI=0); |
< Poddotazy | SQL postupně | UNION dotazy >