Databáze 2011/2012 SQL SELECT II. RNDr.David Hksza, Ph.D. http://siret.cz/hksza
Osnva Pkrčilé SQL IN, EXIST, ANY, ALL GROUP BY, HAVING CASE, COALESCE Mnžinvé perace Cvičení pkrčilé dtazvání v SQL
Klauzule IN Ověření náležení hdnty slupce d výsledku vnřenéh dtazu SELECT * FROM Prduct WHERE PrductID IN (SELECT PrductID FROM SalesOrderDetail) Vyber prdukty, ke kterým existují bjednávky SELECT * FROM Prduct WHERE PrductID NOT IN (SELECT PrductID FROM SalesOrderDetail) Vyber prdukty, ke kterým neexistují bjednávky
Klauzule EXISTS Predikát EXISTS má hdntu TRUE, pkud vnřený dtaz, který je jeh argumentem, vrací neprázdnu mnžinu SELECT * FROM Prduct p WHERE EXISTS (SELECT 1 FROM SalesOrderDetail sd WHERE sd.prductid=p.prductid) Vyber prdukty, ke kterým existují bjednávky SELECT * FROM Prduct p WHERE NOT EXISTS (SELECT 1 FROM SalesOrderDetail sd JOIN SalesOrderHeader sh ON (sd.salesorderid=sh.salesorderid) WHERE sd.prductid=p.prductid AND sh.subttal > 1000) Vyber prdukty, které nefigurují v bjednávkách nad 1000
ALL, ANY/SOME Testvání hdnty prti výsledku vnřenéh dtazu SELECT sh.* FROM SalesOrderHeader sh WHERE 'Brakes' = ALL( SELECT pc.name FROM SalesOrderDetail sd JOIN Prduct p ON (sd.prductid = p.prductid) JOIN PrductCategry pc ON (p.prductcategryid=pc.prductcategryid) WHERE sh.salesorderid = sd.salesorderid ) Vyber bjednávky, v kterých figurují puze bjekty kategrie brzdy SELECT DISTINCT sh.* FROM SalesOrderHeader sh WHERE 'Brakes' = ANY( SELECT pc.name FROM SalesOrderDetail sd JOIN Prduct p ON (sd.prductid = p.prductid) JOIN PrductCategry pc ON (p.prductcategryid=pc.prductcategryid) WHERE sh.salesorderid = sd.salesorderid ) Vyber bjednávky, v kterých figurují bjekty kategrie brzdy
NULL hdnty v ALL, ANY, IN X p ALL(subselect) Vždy UNKNOWN pkud subselect bsahuje NULL hdntu, prtže nelze prvnat s neznámem jinak, než s výsledkem UNKNOWN X p ANY(subselect) NULL nemá vliv pkud subselect bsahuje NULL, prtže stačí aby perace p platila aspň pr jednu hdntu ze subselectu X IN (subselect) NULL nemá vliv pkud subselect bsahuje NULL, prtže stačí aby perace p platila aspň pr jednu hdntu ze subselectu X NOT IN (subselect) Vždy UNKNOWN pkud subselect bsahuje NULL hdntu, prtže nelze říct, zda X není v žádném řádku subselectu
GROUP BY Klauzule GROUP BY seskupuje řádky výsledků pdle splečných hdnt atributů uvedených v GROUP BY klauzuli Agregační perace se aplikují na jedntlivé skupiny SELECT PrductCategryID, COUNT(*) FROM Prduct GROUP BY PrductCategryID Vyber pčty prduktů v jedntlivých kategriích SELECT Name, COUNT(*) FROM Prduct GROUP BY PrductCategryID v SELECT klauzuli lze pužít puze slupce z GROUP BY, neb agregace
GROUP BY SELECT pc.name, COUNT(*) FROM Prduct p JOIN PrductCategry pc ON (p.prductcategryid=pc.prductcategryid) GROUP BY pc.name Vyber názvy kategrií a pčet prduktů v jedntlivých kategriích Šl by i bez pužití GROUP BY s pmcí vnřených dtazů SELECT p.name, SUM(p.ListPrice) AS suma FROM Prduct p JOIN SalesOrderDetail sd ON (p.prductid = sd.prductid) GROUP BY p.name ORDER BY suma DESC Vrať názvy prdkutů a sučet cen přes všechny bjednávky každéh z prduků (tj. klik každý z prduktů vydělal) setříděné sestupně pdle sumy
HAVING Analgie s WHERE klauzulí, ale zatímc WHERE klauzule se aplikuje na každý řádek zdrje, HAVING se aplikuje na celé skupiny, resp. na jejich seskupené hdnty SELECT p.name, SUM(p.ListPrice) AS suma FROM Prduct p JOIN SalesOrderDetail sd ON (p.prductid = sd.prductid) GROUP BY p.name HAVING SUM(p.ListPrice) BETWEEN 10000 AND 20000 Vyber prdukty, které vydělali mezi 10,000 a 20,000
Omezení pčtu řádku TOP k SELECT TOP 3 p.name FROM Prduct p JOIN SalesOrderDetail sd ON (p.prductid = sd.prductid) GROUP BY p.name ORDER BY SUM(p.ListPrice) DESC Vyber 3 nejvíce výdělečné prdukty rw_number() SELECT t.name, t.suma FROM ( SELECT p.name, SUM(p.ListPrice) AS suma, ROW_NUMBER() OVER (ORDER BY SUM(p.ListPrice) DESC) AS rn FROM SalesLT.Prduct p JOIN SalesLT.SalesOrderDetail sd ON (p.prductid = sd.prductid) GROUP BY p.name) t WHERE t.rn >=5 AND t.rn < 10 Vyber pátý až desátý nejvíce výdělečný prdukt
Omezení pčtu řádku rw_number() WITH t AS ( SELECT p.name, SUM(p.ListPrice) AS suma, ROW_NUMBER() OVER (ORDER BY SUM(p.ListPrice) DESC) AS rn FROM SalesLT.Prduct p JOIN SalesLT.SalesOrderDetail sd ON (p.prductid = sd.prductid) GROUP BY p.name ) SELECT t.name, t.suma FROM t WHERE t.rn >=5 AND t.rn < 10 Viz. předchzí, ale s užitím WITH klauzule
CASE CASE umžňuje na základě hdnty vrátit hdntu jinu (jak např. SWITCH v C++ neb Javě) SELECT PrductNumber, Categry = CASE PrductLine WHEN 'R' THEN 'Rad' WHEN 'M' THEN 'Muntain' WHEN 'T' THEN 'Turing' WHEN 'S' THEN 'Other sale items' ELSE 'Nt fr sale' END, Name FROM Prduct
COALESCE Funkce COALESCE vrací první NOT NULL hdntu ze seznamu svých argumentů SELECT COALESCE(hurly_wage * 40 * 52, salary, cmmissin * num_sales) AS 'Ttal Salary' FROM wages ORDER BY 'Ttal Salary Vyber platy v závislsti na vyplněných hdntách slupců hdinvá mzda, plat neb kmise
Sjedncení Mnžinvé perace SELECT PrductMdelID, Name FROM PrductMdel WHERE PrductMdelID NOT IN (3, 4) UNION SELECT PrductMdelID, Name FROM db.glves Vyber mdely, které nemají ID 3 a 4 neb t jsu rukavice Odstraňuje duplicity (mnžinvá perace) Lze pužít UNION ALL pr zachvání duplicitních hdnt
Rzdíl Mnžinvé perace SELECT PrductMdelID, Name FROM PrductMdel WHERE PrductMdelID NOT IN (3, 4) EXCEPT SELECT PrductMdelID, Name FROM Glves Vyber mdely, které nemají ID 3 neb 4 a zárveň t nejsu rukavice
Průnik Mnžinvé perace SELECT Name FROM PrductMdel INTERSECT SELECT Name FROM PrductCategry Vyber názvy mdelů, které jsu sučasně názvy kategrie