Yleiskatsaus
Opetus: 10 min
Harjoitukset: 10 minKysymykset
Miten voin laskea summia, keskiarvoja ja muita yhteenvetoarvoja?
Tavoitteet
Määrittele yhteenlasku ja anna esimerkkejä sen käytöstä.
Kirjoita kyselyitä, jotka laskevat aggregoituja arvoja.
Seuraa aggregointia suorittavan kyselyn suoritusta.
Erittele, miten puuttuvia tietoja käsitellään aggregoinnin aikana.
Haluamme nyt laskea vaihteluvälit ja keskiarvot tiedoillemme.Osaamme valita kaikki päivämäärät
Visited
-taulukosta:SELECT dated FROM Visited;
dated -null-
mutta yhdistääksemme ne,meidän on käytettävä aggregaatiofunktiota, kuten
min
taimax
.Kukin näistä funktioista ottaa syötteenä joukon tietueita,ja tuottaa tulosteena yhden tietueen:SELECT min(dated) FROM Visited;
min(päivätty) SELECT max(dated) FROM Visited;
max(päivätty)
min
jamax
ovat vain kaksi SQL:iin sisäänrakennettua aggregointitoimintoa.Kolme muuta ovatavg
,count
jasum
:SELECT avg(reading) FROM Survey WHERE quant = 'sal';
avg(luku) SELECT count(reading) FROM Survey WHERE quant = 'sal';
count(luku) SELECT sum(reading) FROM Survey WHERE quant = 'sal';
sum(lukeminen) Tässä käytimme
count(reading)
,mutta olisimme yhtä hyvin voineet laskeaquant
tai minkä tahansa muun taulukon kentän,tai jopa käyttääcount(*)
,koska funktio ei välitä itse arvoista,vain siitä kuinka monta arvoa on.SQL antaa meidän tehdä useita aggregointeja kerralla.Voimme esimerkiksi löytää järkevien suolapitoisuusmittausten vaihteluvälin:
SELECT min(reading), max(reading) FROM Survey WHERE quant = 'sal' AND reading <= 1.0;
min(lukema) max(lukema) 0.05 0.21 Voidaan myös yhdistää aggregoidut tulokset ja raakatulokset,tosin tulos saattaa yllättää:
SELECT person, count(*) FROM Survey WHERE quant = 'sal' AND reading <= 1.0;
person count(*) järvi 7 Miksi järven nimi esiintyy Roerichin tai Dyerin sijaan?Vastaus on, että kun sen on aggregoitava kenttä,mutta sille ei ole kerrottu, miten se tehdään, tietokantahallinta valitsee todellisen arvon syöttöjoukosta.Se voi käyttää ensimmäistä käsiteltyä arvoa, viimeistä arvoa tai jotain aivan muuta.
Toinen tärkeä seikka on se, että kun aggregoitavia arvoja ei ole – esimerkiksi kun ei ole rivejä, jotka täyttävät
WHERE
-lausekkeen – aggregaation tulos on ”en tiedä ”eikä nolla tai jokin muu mielivaltainen arvo:SELECT person, max(reading), sum(reading) FROM Survey WHERE quant = 'missing';
henkilö max(lukema) summa(lukema) -null- -null- -null- Yksi viimeinen tärkeä ominaisuus aggregaatiofunktioissa on se, että ne ovat epäjohdonmukaisia muun SQL:n kanssa erittäin hyödyllisellä tavalla.Jos laskemme yhteen kaksi arvoa ja toinen niistä on nolla, tulos on nolla.Jos käytämme
sum
:tä laskemaan yhteen kaikki joukon arvot ja jokin näistä arvoista on nolla, tuloksen pitäisi myös olla nolla.On kuitenkin paljon hyödyllisempää, että aggregaatiofunktiot jättävät nolla-arvot huomiotta ja yhdistävät vain ne arvot, jotka eivät ole nolla.Tämän käyttäytymisen ansiosta voimme kirjoittaa kyselyt seuraavasti:SELECT min(dated) FROM Visited;
min(päivätty) sen sijaan, että joudumme aina suodattamaan nimenomaisesti:
SELECT min(dated) FROM Visited WHERE dated IS NOT NULL;
min(dated) Kaikkien tietueiden yhdistäminen kerralla ei aina ole järkevää.Oletetaan esimerkiksi, että epäilemme, että tiedoissamme on systemaattinen harha ja että joidenkin tutkijoiden säteilylukemat ovat korkeampia kuin toisten.Tiedämme, että tämä ei toimi:
SELECT person, count(reading), round(avg(reading), 2)FROM SurveyWHERE quant = 'rad';
henkilö count(lukema) round(avg(lukema), 2) roe 8 6.56 koska tietokannan ylläpitäjä valitsee yhden mielivaltaisen tutkijan nimen sen sijaan, että laskisi yhteen erikseen jokaisen tutkijan osalta.Koska tiedemiehiä on vain viisi,voisimme kirjoittaa viisi kyselyä muodossa:
SELECT person, count(reading), round(avg(reading), 2)FROM SurveyWHERE quant = 'rad'AND person = 'dyer';
henkilö count(lukeminen) round(avg(lukeminen), 2) dyer 2 8.81 Mutta tämä olisi työlästä,ja jos meillä olisi joskus aineisto, jossa olisi viisikymmentä tai viisisataa tiedemiestä,mahdollisuudet saada kaikki kyselyt oikein ovat pienet.
Mitä meidän on tehtävä, on käskeä tietokannan hallintaa aggregoimaan kunkin tiedemiehen tunnit erikseen
GROUP BY
-lausekkeen avulla:SELECT person, count(reading), round(avg(reading), 2)FROM SurveyWHERE quant = 'rad'GROUP BY person;
henkilö count(lukeminen) pyöristää(avg(lukeminen), 2) värisempi 2 8.81 järvi 2 1.82 pb 3 6.66 roe 1 11.25
GROUP BY
tekee juuri sen, mitä sen nimi antaa ymmärtää: ryhmittelee kaikki tietueet, joilla on sama arvo määritellyssä kentässä, yhteen, jotta aggregointi voi käsitellä jokaisen erän erikseen.Koska kussakin erässä kaikilla tietueilla on sama arvoperson
-kentässä, ei ole enää väliä sillä, että tietokannan hoitaja valitsee mielivaltaisen arvon näytettäväksi aggregoitujenreading
-arvojen rinnalla.Niin kuin voimme lajitella useilla kriteereillä kerralla, voimme myös ryhmitellä useilla kriteereillä.Saadaksemme keskimääräisen lukeman esimerkiksi tutkijan ja mitatun määrän mukaan, lisäämme vain toisen kentän
GROUP BY
-lausekkeeseen:SELECT person, quant, count(reading), round(avg(reading), 2)FROM SurveyGROUP BY person, quant;
henkilö määrä luku(lukema) pyöristää(avg(lukema), 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 järvi sal 4 0.11 järvi lamp lämpö 1 -16.0 pb rad 3 6.66 pb temp 2 -20.0 roe rad 1 11.25 roe sal 2 32.05 Huomaa, että olemme lisänneet
quant
näytettävien kenttien luetteloon,koska muuten tuloksissa ei olisi paljon järkeä.Mennään vielä askeleen pidemmälle ja poistetaan kaikki merkinnät, joissa emme tiedä, kuka on tehnyt mittauksen:
SELECT person, quant, count(reading), round(avg(reading), 2)FROM SurveyWHERE person IS NOT NULLGROUP BY person, quantORDER BY person, quant;
henkilö kvantti count(lukema) pyöristys(avg(lukema), 2) dyer rad 2 8.81 dyer sal 2 0.11 järvi rad 2 1.82 järvi sal 4 0.11 järvi temp 1 -16.0 pb rad 3 6.66 pb temp 2 -20.0 roe rad 1 11.25 roe sal 2 32.05 Katsotaan tarkemmin,tämä kysely:
valitsi
Survey
-taulusta tietueet, joissaperson
-kenttä ei ollut nolla;ryhmitteli nämä tietueet osajoukkoihin siten, että
person
– jaquant
-arvot kussakin osajoukossa olivat samat;järjesteli nämä alaryhmät ensin
person
:n mukaan ja sitten kunkin alaryhmän sisälläquant
:n mukaan;jalaski tietueiden lukumäärän jokaisessa alaryhmässä,laski kunkin alaryhmän keskiarvon
reading
ja valitsi jokaisestaperson
– jaquant
-arvon (ei ole väliä, mitkä, koska ne ovat kaikki samat).Lämpötilalukemien laskeminen
Miten monta lämpötilalukemaa Frank Pabodie kirjasi,ja mikä oli niiden keskiarvo?
Ratkaisu
SELECT count(reading), avg(reading) FROM Survey WHERE quant = 'temp' AND person = 'pb';
lasku(lukema) keskiarvo(lukema) 2 -20.0 Keskiarvo NULL:lla
Arvojoukon keskiarvo on arvojen summa jaettuna arvojen lukumäärällä.Tarkoittaako tämä, että
avg
-funktio palauttaa 2.0 tai 3.0, kun sille annetaan arvot 1.0,null
ja 5.0?Ratkaisu
Vastaus on 3.0.
NULL
ei ole arvo; se on arvon puuttuminen.Sellaisenaan sitä ei oteta mukaan laskentaan.Voit varmistaa tämän suorittamalla tämän koodin:
SELECT AVG(a) FROM ( SELECT 1 AS a UNION ALL SELECT NULL UNION ALL SELECT 5);
Mitä tämä kysely tekee?
Haluamme laskea erotuksen jokaisen yksittäisen säteilylukeman ja kaikkien säteilylukemien keskiarvon välillä.Kirjoitamme kyselyn:
SELECT reading - avg(reading) FROM Survey WHERE quant = 'rad';
Mitä tämä oikeastaan tuottaa, ja keksitkö miksi?
Ratkaisu
Kysely tuottaa vain yhden rivin tuloksia, vaikka oikeasti haluaisimme tuloksen kullekin lukemalle.Funktio
avg()
tuottaa vain yhden arvon, ja koska se ajetaan ensimmäisenä, taulukkoa supistetaan yhteen riviin.reading
-arvo on yksinkertaisesti mielivaltainen.Saadaksemme haluamamme tuloksen meidän olisi suoritettava kaksi kyselyä:
SELECT avg(reading) FROM Survey WHERE quant='rad';
Tämä tuottaa keskiarvon (6.5625), jonka voimme sitten lisätä toiseen kyselyyn:
SELECT reading - 6.5625 FROM Survey WHERE quant = 'rad';
Tämä tuottaa haluamamme tuloksen, mutta voimme yhdistää sen yhdeksi kyselyksi käyttämällä alakyselyjä.
SELECT reading - (SELECT avg(reading) FROM Survey WHERE quant='rad') FROM Survey WHERE quant = 'rad';
Tällöin meidän ei tarvitse suorittaa kahta kyselyä.
Yhteenvetona se, mitä olemme tehneet, on se, että olemme korvanneet
avg(reading)
alkuperäisessä kyselyssä(SELECT avg(reading) FROM Survey WHERE quant='rad')
:llä.järjestys ketjutettaessa
Funktio
group_concat(field, separator)
ketjuttaa kaikki kentän arvot käyttäen määritettyä erotinmerkkiä(tai ’,’ jos erotinta ei ole määritetty).Käytä tätä tuottaaksesi yksirivisen listan tiedemiesten nimistä,esimerkiksi:William Dyer, Frank Pabodie, Anderson Lake, Valentina Roerich, Frank Danforth
Keksitkö keinon järjestää lista sukunimen mukaan?
Kärkikohdat
Käytä aggregointifunktioita useiden arvojen yhdistämiseen.
Aggregointifunktiot eivät huomioi
null
-arvoja.Aggregointi tapahtuu suodatuksen jälkeen.
Käytä GROUP BY -toimintoa osajoukkojen yhdistämiseen erikseen.
Jos kentälle ei ole määritetty aggregointitoimintoa, kysely voi palauttaa mielivaltaisen arvon kyseiselle kentälle.