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.