SQL del 2 Christer Stuxberg christer.stuxberg@im.uu.se Institutionen för Informatik och Media
Översikt Repetition SELECT INSERT Mer SELECT Null sökning Gruppering (GROUP BY) Begränsad gruppering (HAVING) Subselect Queries på flera tabeller Enkla Joins Join på tre tabeller Andra typer av JOIN
Repetition: SELECT SELECT är det viktigaste uttrycket i SQL Varje SELECT-sats ger en ny tabell. Alla kolumnnamn i SELECT måste finnas i tabellerna som listas i FROM WHERE väljer vilka rader som ska vara med i reultattabellen ORDER BY sorterar resultattabellen
Repetition: INSERT INSERT INTO Tabellnamn (kolumn1,kolumn2, ) VALUES (värde1, värde2, ) Tabellnamn är namnet på tabellen som vi vill lägga till en rad i. Kolumnnamn behövs inte alltid. Om kolumnnamn utelämnas så lägger SQL in värdena från första kolumnen i tabellen och framåt Dock så måste värden anges för alla kolumner om kolumnnamn utelämnas
Repetition: INSERT Om man specificerar vilka kolumner man vill lägga in värden i så måste de kolumner som INTE är med i listan vara NULLABLE INSERT INTO Films (filmnum, title, genre) VALUES ( 882, Enter the Dragon, Action ); filmnum title genre restrictions 201 The Spy who Shagged me Action Over 12 678 Harry Potter and the Broomstick Children None 343 Airplane Comedy Over 12 234 Star Wars Action None 882 Enter the Dragon Action
NULL sökning Om vi vill hitta alla filmer i vår tabell som inte har någon restriction: SELECT title, genre FROM Films WHERE restrictions IS NULL; title Enter the Dragon genre Action
Gruppering GROUP BY låter dig hämta data från flera rader och sedan gruppera resultatet på en eller flera kolumner Exempel på Staff från Normaliserings föreläsningen staffno name position salary dcenterno S1500 Tom Daniels Manager 48000 D001 S0003 Sally Adams Assistant 30000 D001 S0010 Mary Martinez Manager 51000 D002 S3250 Robert Chin Assistant 33000 D002 S3333 John Smith Manager 60000 D003
Gruppering Säg att vi vill hitta antalet anställda på varje distributionscenter och se summan av deras löner: SELECT dcenterno, COUNT(staffNo) AS totalstaff, SUM(salary) AS totalsalary FROM Staff GROUP BY dcenterno ORDER BY dcenterno; dcenterno totalstaff totalsalary D001 2 78000 D002 2 84000 D003 1 60000
Gruppering SQL utför vår fråga på följande sätt: 1. Dela in de anställda i grupper beroende på vart de arbetar (dcenterno). I vårt fall har vi tre distributionscenter. 2. För varje grupp, räkna antalet anställda och summera deras lön. 3. Resultatet sorteras i stigande ordning på dcenterno.
Begränsad Gruppering HAVING används tillsammans med GROUP BY för att begränsa vilka grupper som är med i resultattabellen. WHERE används för att filtrera bort rader som inte uppfyller vissa villkor HAVING används för att filtrera bort grupper som inte uppfyller vissa villkor.
HAVING Säg att vi vill hitta antalet anställda på varje distributionscenter som har mer än en anställd och se summan av deras löner: SELECT dcenterno, COUNT(staffNo) AS totalstaff, SUM(salary) AS totalsalary FROM Staff GROUP BY dcenterno HAVING COUNT(staffNo) > 1 ORDER BY dcenterno; dcenterno totalstaff totalsalary D001 2 78000 D002 2 84000
Subselect Vi kan bädda in en SELECT-sats i en annan SELECTsats Resultatet av den inre SELECT-satsen används av den yttre satsen för att bestämma slutresultatet
Subselect Vi har följande tabeller, Staff och DistributionCenter staffno name position salary dcenterno S1500 Tom Daniels Manager 48000 D001 S0003 Sally Adams Assistant 30000 D001 S0010 Mary Martinez Manager 51000 D002 S3250 Robert Chin Assistant 33000 D002 dcenterno dadress dcity dstate dtelno D001 8 Jefferson Way Portland Oregon 503-555-3618 D002 City Center Plaza Seattle Washington 206-555-6756
Subselect Säg att vi vill hitta alla anställda som jobbar på City Center Plaza SELECT staffno, name, position FROM Staff WHERE dcenterno = (SELECT dcenterno FROM DistributionCenter WHERE dadress = City Center Plaza ); staffno name position S0010 Mary Martinez Manager S3250 Robert Chin Assistant
Subselect med EXISTS För varje rad i tabellen, kolla om det finns åtminstone en rad i den andra tabellen som uppfyller villkoret. Subquerien i den här frågan resulterar i TRUE eller FALSE. Så om vi vill hitta alla anställda där deras distributionscenter finns med i tabellen DistributionCenter och att det distributionscenteret ligger i Washington
Subselect med EXISTS SELECT staffno, name, position FROM Staff s WHERE EXISTS (SELECT * FROM DistributionCenter d WHERE s.dcenterno = d.dcenterno AND dstate = Washington ); staffno name position S0010 Mary Martinez Manager S3250 Robert Chin Assistant
Sätt medlemskap för flera resultat Om resultatet för den inre frågan ger fler än en rad så kan vi inte använda = utan då får vi använda IN istället Exempel: Om vi vill hitta alla anställda som arbetar på ett distributionscenter i antingen Oregon eller Washington: SELECT staffno, name, position FROM Staff WHERE dcenterno IN (SELECT dcenterno FROM DistributionCenter WHERE dstate = Oregon OR dstate = Washington );
Ett annat sätt att få samma resultat SELECT staffno, name, position FROM Staff s, DistributionCenter d WHERE (dstate = Oregon OR dstate = Washington ) AND s.dcenterno = d.dcenterno;
Queries på flera tabeller Hittills har vi endast hämtat ut information från kolumner i en tabell För att hämta information från kolumner i flera tabeller så måste vi använda JOIN JOIN kombinerar information från flera tabeller genom att koppla ihop dem på värdet från en kolumn från vardera tabell
INNER JOIN (eller JOIN) En vanlig JOIN kan göras på flera sätt Actors actorno actorname 008 Mike Myers 865 Anthony Hopkins 324 Daniel Radcliffe 964 Harrison Ford 535 Keanu Reeves ActorsInFilms actorno filmno character 008 201 Austin Powers 865 134 Hannibal Lecter 324 678 Harry Potter 964 234 Han Solo 964 555 Indiana Jones 878 678 Hermione Granger
Säg att vi vill ha namnet på skådespelaren och vilken karaktär de spelat SELECT actorname, character FROM Actors a, ActorsInFilms f WHERE a.actorno = f.actorno; actorname Mike Myers Anthony Hopkins Daniel Radcliffe Harrison Ford Harrison Ford character Austin Powers Hannibal Lecter Harry Potter Han Solo Indiana Jones
JOIN Du kan även få ut samma information på följande sätt: SELECT actorname, character FROM Actor a JOIN ActorInFilm f ON a.actorno = f.actorno;
JOIN på tre tabeller Om vi nu vill ha ut information från tre tabeller (Actors, ActorsInFilms och Films) för att hämta ut skådespelare, karaktär och film: filmno title genre restrictions 201 The Spy who Shagged me Action Over 12 678 Harry Potter and the Broomstick Children None 134 Silence of the Lambs Horror Over 17 343 Airplane Comedy Over 12 234 Star Wars Action None 555 Raiders of the Lost Ark Action Over 12
JOIN på tre tabeller SELECT actorname, character, title FROM Actors a, ActorsInFilms af, Films f WHERE a.actorno = af.actorno AND af.filmno = f.filmno; actorname character title Mike Myers Austin Powers The Spy who Shagged me Anthony Hopkins Hanniba Lecter Silence of the Lambs Daniel Radcliffe Harry Potter Harry Potter and the Broomstick Harrison Ford Han Solo Star Wars Harrison Ford Indiana Jones Raiders of the Lost Ark
Andra typer av JOIN
LEFT (OUTER) JOIN Om vi vill ha ut all information från alla rader i första tabellen (left) men även lägga till information från den andra tabellen (right) om det finns SELECT actorname, character FROM Actors a LEFT JOIN ActorsInFilms f ON a.actorno = f.actorno; actorname Mike Myers Anthony Hopkins Daniel Radcliffe Harrison Ford character Austin Powers Hannibal Lecter Harry Potter Han Solo Harrison Ford Indiana Jones Keanu Reeves
RIGHT (OUTER) JOIN Om vi vill ha ut all information från alla rader i andra tabellen (right) men även lägga till information från den första tabellen (left) om det finns SELECT actorname, character FROM Actors a RIGHT JOIN ActorsInFilms f ON a.actorno = f.actorno; actorname Mike Myers Anthony Hopkins Daniel Radcliffe Harrison Ford character Austin Powers Hannibal Lecter Harry Potter Han Solo Harrison Ford Indiana Jones Hermione Granger
FULL OUTER JOIN Om vi vill ha ut all information från alla rader i första tabellen (left) och lägga till all information från den andra tabellen (right) SELECT actorname, character FROM Actors a FULL OUTER JOIN ActorsInFilms f ON a.actorno = f.actorno; actorname Mike Myers Anthony Hopkins Daniel Radcliffe character Austin Powers Hannibal Lecter Harry Potter Harrison Ford Harrison Ford Han Solo Indiana Jones Keanu Reeve Hermione Granger
Exempel på olika typer av JOIN Bilden är stor och kommer på nästa slide
CROSS JOIN
UNION UNION används för att skapa en lista med information från två tabeller actorno actorname 008 Mike Myers 865 Anthony Hopkins 324 Daniel Radcliffe 964 Harrison Ford 535 Keanu Reeves actorno filmno character 008 201 Austin Powers 865 134 Hannibal Lecter 324 678 Harry Potter 964 234 Han Solo 964 555 Indiana Jones 878 678 Hermione Granger
UNION SELECT actorname AS names FROM Actors UNION SELECT character FROM ActersInFilms; UNION ger dig unika namn inga dubletter. Om man vill ha dubbletter så använder man UNION ALL istället names Mike Myers Anthony Hopkins Daniel Radcliffe Harrison Ford Keanu Reeves Austin Powers Hannibal Lecter Harry Potter Han Solo Indiana Jones Hermione Granger