Översikt
Undervisning: 10 min
Övningar: 10 minFrågor
Hur kan jag beräkna summor, medelvärden och andra sammanfattande värden?
Mål
Definiera aggregering och ge exempel på dess användning.
Skriv frågor som beräknar aggregerade värden.
Spåra utförandet av en fråga som utför aggregering.
Förklara hur saknade data hanteras vid aggregering.
Vi vill nu beräkna intervall och medelvärden för våra data.Vi vet hur man väljer alla datum från tabellen
Visited
:SELECT dated FROM Visited;
dated -null-
men för att kombinera dem måste vi använda en aggregeringsfunktion som
min
ellermax
.Var och en av dessa funktioner tar en uppsättning poster som indata och producerar en enda post som utdata:SELECT min(dated) FROM Visited;
min(daterad) SELECT max(dated) FROM Visited;
max(daterad)
min
ochmax
är bara två av de aggregeringsfunktioner som är inbyggda i SQL.Tre andra äravg
,count
ochsum
:SELECT avg(reading) FROM Survey WHERE quant = 'sal';
avg(reading) SELECT count(reading) FROM Survey WHERE quant = 'sal';
count(reading) .
SELECT sum(reading) FROM Survey WHERE quant = 'sal';
sum(reading) Vi använde
count(reading)
här,men vi kunde lika gärna ha räknatquant
eller något annat fält i tabellen, eller till och med använtcount(*)
, eftersom funktionen inte bryr sig om själva värdena, utan bara om hur många värden det finns.SQL låter oss göra flera aggregeringar samtidigt.Vi kan till exempel hitta intervallet för känsliga salthaltsmätningar:
SELECT min(reading), max(reading) FROM Survey WHERE quant = 'sal' AND reading <= 1.0;
min(mätning) max(mätning) 0,05 0.21 Vi kan också kombinera aggregerade resultat med råa resultat,även om resultatet kan överraska dig:
SELECT person, count(*) FROM Survey WHERE quant = 'sal' AND reading <= 1.0;
person count(*) lake 7 Varför förekommer Lake i stället för Roerich eller Dyer?Svaret är att när databashanteraren måste aggregera ett fält, men inte får veta hur den ska göra, väljer den ett faktiskt värde från inmatningsuppsättningen.Den kan använda det första som behandlas, det sista eller något helt annat.
Ett annat viktigt faktum är att när det inte finns några värden att aggregera – till exempel när det inte finns några rader som uppfyller
WHERE
-klausulen – är aggregeringens resultat ”vet inte ”snarare än noll eller något annat godtyckligt värde:SELECT person, max(reading), sum(reading) FROM Survey WHERE quant = 'missing';
person max(läsning) sum(läsning) -noll- -null- -null- En sista viktig egenskap hos aggregeringsfunktioner är att de är inkonsekventa med resten av SQL på ett mycket användbart sätt.Om vi adderar två värden och ett av dem är ogiltigt blir resultatet ogiltigt.Om vi använder
sum
för att addera alla värden i en uppsättning och något av dessa värden är ogiltigt blir resultatet också ogiltigt.Det är dock mycket mer användbart att aggregeringsfunktioner ignorerar ogiltiga värden och endast kombinerar de värden som inte är ogiltiga.Detta beteende gör att vi kan skriva våra frågor som:SELECT min(dated) FROM Visited;
min(daterad) i stället för att alltid behöva filtrera explicit:
SELECT min(dated) FROM Visited WHERE dated IS NOT NULL;
min(dated) Aggregering av alla poster på en gång är inte alltid meningsfullt.Anta till exempel att vi misstänker att det finns en systematisk bias i våra data, och att vissa forskares strålningsmätningar är högre än andra.Vi vet att detta inte fungerar:
SELECT person, count(reading), round(avg(reading), 2)FROM SurveyWHERE quant = 'rad';
person count(reading) round(avg(reading), 2) roe 8 6.56 eftersom databashanteraren väljer en enda godtycklig forskares namn i stället för att aggregera separat för varje forskare.Eftersom det bara finns fem forskare kan vi skriva fem förfrågningar av följande form:
SELECT person, count(reading), round(avg(reading), 2)FROM SurveyWHERE quant = 'rad'AND person = 'dyer';
person count(reading) round(avg(reading), 2) dyer 2 8.81 Men detta skulle vara tråkigt, och om vi någonsin hade en datamängd med femtio eller femhundra vetenskapsmän är chansen liten att vi skulle få alla dessa frågor rätt.
Vad vi behöver göra är att be databashanteraren att sammanställa timmarna för varje forskare separat med hjälp av en
GROUP BY
-klausul:SELECT person, count(reading), round(avg(reading), 2)FROM SurveyWHERE quant = 'rad'GROUP BY person;
person count(reading) round(avg(reading), 2) dyer 2 8.81 sjö 2 1.82 pb 3 6.66 roe 1 11.25
GROUP BY
gör exakt vad namnet antyder: grupperar alla poster med samma värde för det angivna fältet tillsammans så att aggregeringen kan behandla varje batch separat.Eftersom alla poster i varje sats har samma värde förperson
spelar det inte längre någon roll att databashanteraren väljer ett godtyckligt värde som visas vid sidan av de aggregeradereading
-värdena.Samma som vi kan sortera efter flera kriterier samtidigt, kan vi också gruppera efter flera kriterier.För att få fram den genomsnittliga avläsningen efter vetenskapsman och uppmätt kvantitet är det bara att lägga till ytterligare ett fält i
GROUP BY
-klausulen:SELECT person, quant, count(reading), round(avg(reading), 2)FROM SurveyGROUP BY person, quant;
person kvant count(reading) round(avg(reading), 2) -null- sal 1 0.06 -null- temp 1 -26.0 dyer rad 2 8.81 dyer sal 2 0.11 lake rad 2 1.82 sjö sal 4 0.11 sjö temp 1 -16.0 pb rad 3 6.66 pb temp 2 -20.0 roe rad 1 11.25 roe sal 2 32.05 Notera att vi har lagt till
quant
i listan över fält som visas, eftersom resultaten inte skulle vara särskilt logiska annars.Vi kan gå ett steg längre och ta bort alla poster där vi inte vet vem som utförde mätningen:
SELECT person, quant, count(reading), round(avg(reading), 2)FROM SurveyWHERE person IS NOT NULLGROUP BY person, quantORDER BY person, quant;
person kvant räknar(läsning) rundar(avg(läsning), 2) dyer rad 2 8.81 dyer sal 2 0.11 sjö rad 2 1.82 sjö sal 4 0.11 lake temp 1 -16.0 pb rad 3 6.66 pb temp 2 -20.0 roe rad 1 11.25 roe sal 2 32.05 Om man tittar närmare på denna fråga:
väljer ut poster från tabellen
Survey
där fältetperson
inte är noll;grupperar dessa poster i undergrupper så att värdena
person
ochquant
i varje undergrupp är desamma;ordnade dessa undergrupper först efter
person
och sedan inom varje undergrupp efterquant
, ochräknade antalet poster i varje undergrupp, beräknade genomsnittet
reading
i varje och valde ettperson
– ochquant
-värde från var och en av dem (det spelar ingen roll vilka, eftersom de alla är lika).Räkna temperaturavläsningar
Hur många temperaturavläsningar registrerade Frank Pabodie och vilket var deras medelvärde?
Lösning
SELECT count(reading), avg(reading) FROM Survey WHERE quant = 'temp' AND person = 'pb';
räkning(avläsning) avg(avläsning) 2 -20.0 Medelvärdeberäkning med NULL
Genomsnittet av en uppsättning värden är summan av värdena dividerat med antalet värden.Betyder detta att funktionen
avg
returnerar 2,0 eller 3,0 när den får värdena 1,0,null
och 5,0?Lösning
Svaret är 3,0.
NULL
är inte ett värde; det är frånvaron av ett värde.Det ingår alltså inte i beräkningen.Du kan bekräfta detta genom att köra den här koden:
SELECT AVG(a) FROM ( SELECT 1 AS a UNION ALL SELECT NULL UNION ALL SELECT 5);
Vad gör den här frågan?
Vi vill beräkna skillnaden mellan varje enskild strålningsmätning och genomsnittet av alla strålningsmätningar.Vi skriver frågan:
SELECT reading - avg(reading) FROM Survey WHERE quant = 'rad';
Vad ger detta egentligen och kan du tänka dig varför?
Lösning
Frågan ger bara en rad med resultat när vi egentligen vill ha ett resultat för var och en av avläsningarna.
avg()
-funktionen ger bara ett enda värde, och eftersom den körs först, reduceras tabellen till en enda rad.Värdetreading
är helt enkelt ett godtyckligt värde.För att uppnå det vi ville skulle vi behöva köra två förfrågningar:
SELECT avg(reading) FROM Survey WHERE quant='rad';
Detta ger medelvärdet (6.5625), som vi sedan kan infoga i en andra fråga:
SELECT reading - 6.5625 FROM Survey WHERE quant = 'rad';
Detta ger det vi vill ha, men vi kan kombinera detta till en enda fråga med hjälp av underfrågor.
SELECT reading - (SELECT avg(reading) FROM Survey WHERE quant='rad') FROM Survey WHERE quant = 'rad';
På så sätt behöver vi inte utföra två förfrågningar.
Sammanfattningsvis är det vi har gjort att ersätta
avg(reading)
med(SELECT avg(reading) FROM Survey WHERE quant='rad')
i den ursprungliga förfrågan.
Ordning vid sammankoppling
Funktionen
group_concat(field, separator)
samkör alla värden i ett fält med hjälp av det angivna separatortecknet (eller ’,’ om separatorn inte är angiven).Använd den här funktionen för att producera en enradig lista över vetenskapsmännens namn, till exempel:William Dyer, Frank Pabodie, Anderson Lake, Valentina Roerich, Frank Danforth
Kan du hitta ett sätt att ordna listan efter efternamn?
Nyckelpunkter
Använd aggregeringsfunktioner för att kombinera flera värden.
Aggregeringsfunktioner ignorerar
null
värden.Aggregering sker efter filtrering.
Använd GROUP BY för att kombinera delmängder separat.
Om ingen aggregeringsfunktion har angetts för ett fält kan frågan returnera ett godtyckligt värde för det fältet.