Itt kezdődik? Ez a lecke egy teljes hosszúságú oktatóanyag része az SQL használatának az adatelemzéshez. Nézze meg az elejét.
Ebben a leckében a következőket fogjuk ismertetni:
- Bevezetés az ablakfunkciókba
- Alapvető ablakos szintaxis
- A szokásos gyanúsítottak: SUM, COUNT és AVG
- ROW_NUMBER ()
- RANK () és DENSE_RANK ()
- NTILE
- HACS és VEZET
- Ablak álnév meghatározása
- Fejlett ablakolási technikák
Ez a lecke Washington DC Capital Bikeshare Programjának adatait használja fel, amely közzéteszi részletes utazási szintű történelmi adatok a weboldalukon. Az adatokat 2014 februárjában töltötték le, de csak a 2012 első negyedévében gyűjtött adatokra korlátozódnak. Minden sor egy menetet jelent. A legtöbb mező magától értetődő, kivéve a rider_type
-t: A “Regisztrált” havi tagságot jelent a túramegosztó programban, a “Alkalmi” azt jelenti, hogy a versenyző 3 napos bérletet vásárolt. A start_time
és a end_time
mezőket eredeti dátumformájukból kitisztítottuk, hogy megfeleljenek az SQL dátum formázásának – ebben a táblázatban időbélyegként tárolódnak.
Bevezetés az ablakfunkciókba
A PostgreSQL dokumentációja kiváló munkát végez az Ablakfunkciók fogalmának bevezetésében:
Egy ablakfüggvény számításokat hajt végre az aktuális sorhoz valamilyen módon kapcsolódó táblázatsorok között. Ez összehasonlítható azzal a típusú számítással, amelyet egy összesítő függvénnyel lehet elvégezni. De a szokásos összesítő függvényekkel ellentétben egy ablak használata A függvény nem okozza, hogy a sorok egyetlen kimeneti sorba csoportosuljanak – a sorok megtartják külön identitásukat. A kulisszák mögött az ablak funkció nemcsak a lekérdezés eredményének aktuális sorához képes hozzáférni.
Ennek a legpraktikusabb példája a futó összesítés:
Láthatja, hogy a fenti lekérdezés összesítést hoz létre (running_total
) a GROUP BY
használata nélkül. Bontjuk le a szintaxist és nézzük meg, hogyan működik.
Alapvető szintaxis
A fenti összesítés első része, SUM(duration_seconds)
, úgy néz ki, mint bármely más összesítés. A OVER
hozzáadásával ablakfüggvényként jelöljük meg. A fenti összesítést úgy olvashatja el, hogy “vegye fel a duration_seconds
a teljes eredményhalmazon, start_time
sorrendben. “
Ha szűkíteni szeretné az ablakot a teljes adatkészletről az egyes csoportokon belül, az adatkészlethez, ehhez használhatja a PARTITION BY
t:
A fenti lekérdezés a start_terminal
szerint rendezi a lekérdezést. . A start_terminal
minden egyes értékén belül rendezi a következő: start_time
, és az aktuális soron futó összes összeg és a duration_seconds
. Görgessen lefelé, amíg a start_terminal
érték megváltozik, és észreveszi, hogy a running_total
elölről indul. Ez történik, ha a (z) PARTITION BY
használatával csoportosít. Ha még mindig elüt a ORDER BY
, egyszerűen megrendeli a kijelölt oszlop. (s) ugyanúgy, mint a ORDER BY
záradék, azzal a különbséggel, hogy minden partíciót különként kezel. Ez létrehozza a futó összeget is – ORDER BY
nélkül minden érték egyszerűen összeadódik a duration_seconds
értékekkel a megfelelő start_terminal
. Próbálja meg futtatni a fenti lekérdezést ORDER BY
nélkül, hogy ötletet kapjon:
A ORDER
és PARTITION
meghatározza, hogy mi az úgynevezett” ablak “- az adatok rendezett részhalmaza, amelyre a számításokat végezzük.
Megjegyzés: Az ablakfüggvények és a standard összesítések nem használhatók ugyanazokban lekérdezés. Pontosabban: “nem vehet fel ablakfunkciókat egy GROUP BY
záradékba.
Gyakorlati probléma
Írjon egy lekérdezésmódosítást a fenti példa lekérdezésről, amely az egyes futások időtartamát mutatja a versenyzők által az egyes start_terminálokból felhalmozott összes idő százalékában.
Próbálja ki Lásd a választ
A szokásos gyanúsítottak: SUM, COUNT és AVG
Ablakfunkciók használatakor ugyanazokat az összesítéseket alkalmazhatja, mint normál körülmények között – SUM
, COUNT
és AVG
. Ezek megértésének legegyszerűbb módja az előző példa újrafuttatása néhány további funkcióval. Létrehozás
Alternatív megoldásként ugyanazok a függvények az ORDER BY
paranccsal:
Győződjön meg róla, hogy az előző két lekérdezést bekapcsolta a Mode-ba és futtatta őket. Ez a következő gyakorlati probléma nagyon hasonlít a példákhoz, ezért próbálkozzon a fenti kód módosításával, ne pedig a semmiből induljon.
Gyakorlati probléma
Írjon egy lekérdezést, amely a kerékpáros túrák teljes futási idejét mutatja (hasonlóan a utolsó példa), de end_terminal
szerint csoportosítva, a menetidővel csökkenő sorrendben rendezve.
Próbálja ki Nézze meg a választ
ROW_NUMBER ()
ROW_NUMBER()
pontosan azt csinálja, aminek hangzik – megjeleníti az adott sor számát. Első értéke 1, a sorokat pedig az ablak utasítás ORDER BY
részének megfelelően számozza. A ROW_NUMBER()
nem igényel változó megadását a zárójelben:
A PARTITION BY
záradék használata lehetővé teszi, hogy kezdje meg az 1-es számolást minden partícióban. A következő lekérdezés újrakezdi az egyes terminálok számlálását:
RANK () és DENSE_RANK ()
RANK()
kissé eltér a ROW_NUMBER()
-től. Ha például a start_time
alapján rendel, akkor előfordulhat, hogy egyes terminálok két azonos kezdési idõvel rendelkeznek. Ebben az esetben azonos rangot kapnak, míg a ROW_NUMBER()
különböző számokat ad nekik. A következő lekérdezésben észreveszi a start_terminal
31000 4. és 5. megfigyelését – mindkettő 4-es, és a következő eredmény 6-os rangot kap:
Alkalmazásától függően használhatja a DENSE_RANK()
szót is a RANK()
helyett. Képzeljünk el egy olyan helyzetet, amikor három bejegyzésnek ugyanaz az értéke. Bármelyik parancs használatával mindannyian azonos rangot kapnak. E példa kedvéért mondjuk “s” azt “s” 2. ” A két parancs így értékelné a következő eredményeket másképp:
-
RANK()
az azonos soroknak 2-es rangot adna, majd a 3. helyet kihagyja és 4, tehát a következő eredmény 5 lenne. -
DENSE_RANK()
akkor is minden azonos sornak 2-es rangot adna, de a következő sor 3-as lesz. a sorok kihagyásra kerülnek.
Gyakorlati probléma
Írjon egy lekérdezést, amely az 5 leghosszabb menetet mutatja az egyes indulási terminálokról, terminálok szerint rendezve, és a leghosszabb és a legrövidebb utazások az egyes terminálokon belül. Korlátozzon azokra a túrákra, amelyek 2012. január 8. előtt történtek.
Próbálja ki Lásd a választ
NTILE
Az ablakfüggvényekkel meghatározhatja, hogy egy adott sor melyik percentilisbe (vagy kvartilisbe, vagy bármely más felosztásba) esik. A szintaxis: NTILE(*# of buckets*)
. Ebben az esetben az ORDER BY
határozza meg, hogy melyik oszlopot használja a kvartilisek (vagy bármilyen tetszőleges számú “csempe” meghatározásához) adja meg). Például:
A fenti lekérdezés eredményeit megnézve láthatja, hogy a percentile
oszlop nem pontosan úgy számol, ahogyan azt elvárhatja. Ha csak két rekordja volt, és te a percentiliseket mérted, akkor elvárhatod, hogy az egyik rekord meghatározza az 1., a másik rekord pedig a 100. százalékot. A NTILE
függvény használatával valójában egy 1. és egy 2. percentilisben lévő rekord látható. Ezt láthatja a 31000 – a percentile
oszlop csak numerikus rangsornak tűnik. Ha lefelé görget a start_terminal
31007 pontig, akkor láthatja, hogy megfelelően kiszámítja a percentiliseket, mert 100-nál több rekord van a start_terminal
számára. Ha nagyon kicsi ablakokkal dolgozik, ne feledje ezt, és fontolja meg kvartilis vagy hasonlóan kicsi használatát sávok.
Gyakorlati probléma
Írjon olyan lekérdezést, amely csak az utazás időtartamát és a százalékot mutatja ez az időtartam esik (a teljes adatkészleten – nem particionálva a terminálon).
Próbálja ki Nézze meg a választ
HACS és VEZET
Gyakran hasznos lehet összehasonlítani a sorokat az előző vagy a következő sorokkal, különösen ha értelmes sorrendben kapta meg az adatokat. Használhatja a LAG
vagy a LEAD
elemeket olyan oszlopok létrehozásához, amelyek értékeket húznak más sorok – csak annyit kell tennie, hogy megadja, melyik oszlopból húzza ki, és hány sorral távolabb szeretné végrehajtani a húzást. LAG
húz az előző sorokból, és LEAD
a következő sorokból húz:
Ez különösen akkor hasznos, ha kiszámolni szeretné különbségek a sorok között:
A difference
oszlop első sora null, mert nincs előző sor, ahonnan ki lehetne húzni. Ehhez hasonlóan a LEAD
használatával nullákat hoz létre az adatkészlet végén. Ha egy kicsit tisztábbá szeretné tenni az eredményeket, akkor a nullák eltávolításához egy külső lekérdezésbe csomagolhatja:
Ablak-álnév meghatározása
Ha írást tervez több ablakfunkció ugyanabba a lekérdezésbe, ugyanazon ablak használatával álnevet hozhat létre.Vegyük a fenti NTILE
példát:
Ez így írható át:
A WINDOW
a záradéknak, ha szerepel, mindig a WHERE
záradék után kell lennie.
Fejlett ablakkezelési technikák
Megtekintheti az ablakok teljes listáját. funkciók a Postgres-ben (a szintaxis mód használja) a Postgres dokumentációjában. Ha ablakfunkciókat használ egy csatlakoztatott adatbázisban, akkor nézze meg a rendszerének megfelelő szintaxis útmutatót.