PostgreSQL實(shí)現(xiàn)透視表查詢(xún)的方法詳解
需求說(shuō)明
解釋此函數(shù)如何工作的最簡(jiǎn)單方法是使用帶有數(shù)據(jù)透視表的示例。首先,我們將從實(shí)際角度解釋我們最初的觀點(diǎn),然后定義所需的數(shù)據(jù)透視表。
假設(shè)我們是老師,需要統(tǒng)計(jì)你教所有科目的成績(jī)(語(yǔ)言、音樂(lè)等),學(xué)校為你提供了記錄所有評(píng)估或測(cè)試結(jié)果的系統(tǒng)。下面的SQL語(yǔ)句將顯示之前加載到系統(tǒng)中的計(jì)算結(jié)果:
SELECT * FROM evaluations
示例數(shù)據(jù)如下:
| Student | Subject | Evaluation_result | Evaluation_day |
|---|---|---|---|
| Smith, John | Music | 7.0 | 2016-03-01 |
| Smith, John | Maths | 4.0 | 2016-03-01 |
| Smith, John | History | 9.0 | 2016-03-22 |
| Smith, John | Language | 7.0 | 2016-03-15 |
| Smith, John | Geography | 9.0 | 2016-03-04 |
| Gabriel, Peter | Music | 2.0 | 2016-03-01 |
| Gabriel, Peter | Maths | 10.0 | 2016-03-01 |
| Gabriel, Peter | History | 7.0 | 2016-03-22 |
| Gabriel, Peter | Language | 4.0 | 2016-03-15 |
| Gabriel, Peter | Geography | 10.0 | 2016-03-04 |
- 期望結(jié)果
下面的表格可以很容易地跟蹤學(xué)生的進(jìn)度。在計(jì)算機(jī)科學(xué)中,我們稱(chēng)這種網(wǎng)格為透視表。如果分析數(shù)據(jù)透視表,你會(huì)發(fā)現(xiàn)我們使用原始數(shù)據(jù)中的值作為列標(biāo)題或字段名(在本例中是地理、歷史、數(shù)學(xué)等)。
希望的數(shù)據(jù)格式如下:
| Student | Geography | History | Language | Maths | Music |
|---|---|---|---|---|---|
| Gabriel, Peter | 10.0 | 7.0 | 4.0 | 10.0 | 2.0 |
| Smith, John | 9.0 | 9.0 | 7.0 | 4.0 | 7.0 |
啟用tablefunc擴(kuò)展
正如我們前面提到的,crosstab 函數(shù)是PostgreSQL擴(kuò)展tablefunc的一部分。要調(diào)用crosstab 函數(shù),必須首先通過(guò)執(zhí)行以下SQL命令啟用tablefunction擴(kuò)展:
CREATE extension tablefunc;
crosstab 函數(shù)
crosstab 函數(shù)接收SQL SELECT命令作為參數(shù),該參數(shù)必須符合以下限制:
- SELECT必須返回3列。
- SELECT中的第一列將是數(shù)據(jù)透視表或最終結(jié)果中每一行的標(biāo)識(shí)符。在我們的例子中,這是學(xué)生的名字。注意學(xué)生的名字(John Smith和Peter Gabriel)是如何出現(xiàn)在第一列中的。
- SELECT中的第二列表示透視表中的類(lèi)別。在我們的例子中,這些類(lèi)別是學(xué)校的科目。需要注意的是,該列的值將擴(kuò)展到數(shù)據(jù)透視表中的許多列中。如果第二列返回5個(gè)不同的值(地理、歷史等),則數(shù)據(jù)透視表將有5列。
- SELECT中的第三列表示分配給數(shù)據(jù)透視表的每個(gè)單元格的值。這些是我們示例中的求值結(jié)果。
如果我們把數(shù)據(jù)透視表看作一個(gè)二維數(shù)組,那么第一個(gè)SELECT列是數(shù)組的第一個(gè)維度,第二個(gè)SELECT列是第二個(gè)維度,第三個(gè)是數(shù)組元素的值。比如grid [first_column_value, second_column_value] = third_column_value。
SELECT student, subject, evaluation_result FROM evaluations ORDER BY 1,2
crosstab 函數(shù)在SELECT語(yǔ)句的FROM子句中調(diào)用。我們必須定義將進(jìn)入最終結(jié)果的列和數(shù)據(jù)類(lèi)型的名稱(chēng)。就我們的目的而言,最終結(jié)果定義為:
AS final_result(Student TEXT, Geography NUMERIC,History NUMERIC,Language NUMERIC,Maths NUMERIC,Music NUMERIC)
整合上面的內(nèi)容,完整的語(yǔ)句:
SELECT *
FROM crosstab( 'select student, subject, evaluation_result from evaluations order by 1,2')
AS final_result(Student TEXT, Geography NUMERIC,History NUMERIC,Language NUMERIC,Maths NUMERIC,Music NUMERIC);
查詢(xún)結(jié)果如下:
| Student | Geography | History | Language | Maths | Music |
|---|---|---|---|---|---|
| Gabriel, Peter | 10.0 | 7.0 | 4.0 | 10.0 | 2.0 |
| Smith, John | 9.0 | 9.0 | 7.0 | 4.0 | 7.0 |
透視表實(shí)戰(zhàn)示例
從單個(gè)數(shù)據(jù)集,我們可以生成許多不同的數(shù)據(jù)透視表。讓我們繼續(xù)以教師和班級(jí)為例,看看我們的一些選項(xiàng)。
查詢(xún)學(xué)生每月成績(jī)
作為老師,我們可能還需要一份學(xué)生今年迄今為止的評(píng)估結(jié)果報(bào)告。例如,假設(shè)我們想要獲得約翰·史密斯從3月到7月的平均評(píng)價(jià)。在如下的網(wǎng)格中,表格看起來(lái)是這樣的:
| month text | geography numeric | history numeric | language numeric | maths numeric | music numeric |
|---|---|---|---|---|---|
| 3 | 9.00 | 9.00 | 7.00 | 4.00 | 7.00 |
| 4 | 4.00 | 7.50 | 7.00 | 4.00 | 5.66 |
| 5 | 8.00 | 6.00 | 7.00 | 7.00 | 7.00 |
| 6 | 7.50 | 7.00 | 7.00 | 7.00 | 8.00 |
| 7 | 6.66 | 9.00 | 7.75 | 10.00 | 6.00 |
實(shí)現(xiàn)透視表SQL:
SELECT *
FROM crosstab( 'select extract(month from period)::text, subject.name,
trunc(avg(evaluation_result),2)
from evaluation, subject
where evaluation.subject_id = subject.subject_id and student_id = 1
group by 1,2 order by 1,2') AS final_result(Month TEXT, Geography NUMERIC,History NUMERIC,Language NUMERIC,Maths NUMERIC,Music NUMERIC);
處理不完整記錄
我們也可以稱(chēng)這一節(jié)為“交叉表的限制以及如何解決它”。在討論這個(gè)問(wèn)題之前,讓我們先來(lái)設(shè)定一下場(chǎng)景:
假設(shè)你想看看是否有些學(xué)生在某些科目上沒(méi)有考試分?jǐn)?shù)。也許你可以嘗試前面的查詢(xún),為July添加一個(gè)WHERE子句。代碼看起來(lái)像這樣:
SELECT *
FROM crosstab( 'select student, subject, evaluation_result from evaluations where extract (month from evaluation_day) = 7 order by 1,2')
AS final_result(Student TEXT, Geography NUMERIC,History NUMERIC,Language NUMERIC,Maths NUMERIC,Music NUMERIC);
下面的數(shù)據(jù)透視表是該查詢(xún)的結(jié)果。我們很快就可以看到,我們沒(méi)有給彼得的語(yǔ)言、數(shù)學(xué)和音樂(lè)評(píng)分。
| Student | Geography | History | Language | Maths | Music |
|---|---|---|---|---|---|
| Gabriel, Peter | 10.0 | 6.0 | 7.00 | ||
| Smith, John | 6.0 | 8.0 | 6.0 | 9.0 | 4.0 |
但是,如果我們嘗試常規(guī)查詢(xún)以獲得Peter在7月份的成績(jī)……
SELECT * from evaluations where extract ( month from evaluation_day)=7 and student like 'Gabriel, Peter'
當(dāng)然,第二個(gè)查詢(xún)是正確的,因?yàn)樗@示的是原始數(shù)據(jù)。問(wèn)題是數(shù)據(jù)透視表構(gòu)建過(guò)程中,有些種類(lèi)的信息缺失。為了解決這個(gè)問(wèn)題,我們可以使用帶有第二個(gè)參數(shù)的交叉表函數(shù),該參數(shù)表示完整的類(lèi)別列表。如果存在缺失值,數(shù)據(jù)透視表仍將正確構(gòu)建。
第二個(gè)參數(shù)內(nèi)容:‘select name from subject order by 1’ ,完整語(yǔ)句如下:
SELECT *
FROM crosstab( 'select student, subject, evaluation_result from evaluations
where extract (month from evaluation_day) = 7 order by 1,2',
'select name from subject order by 1')
AS final_result(Student TEXT, Geography NUMERIC,History NUMERIC,Language NUMERIC,Maths NUMERIC,Music NUMERIC);
現(xiàn)在輸出結(jié)果包括缺失科目,并使用–表示:
| Student | Geography | History | Language | Maths | Music |
|---|---|---|---|---|---|
| Gabriel, Peter | 10.0 | – | 6.0 | – | – |
| Smith, John | 6.0 | 8.0 | 6.0 | 9.0 | 4.0 |
練習(xí)數(shù)據(jù)
數(shù)據(jù)透視表為我們提供了一種不同的方式來(lái)查看數(shù)據(jù)。此外,我們可以使用交叉表函數(shù)基于相同的原始數(shù)據(jù)創(chuàng)建不同的數(shù)據(jù)透視表。嘗試構(gòu)建一個(gè)數(shù)據(jù)透視表,根據(jù)下表中的原始數(shù)據(jù)顯示每個(gè)城市和月份的最高溫度。
CREATE TABLE weather (city text, when timestamp, temperature float);
| City | When | Temperature |
|---|---|---|
| Miami | 2016-01-01 08:00:00 | 68.6 |
| Miami | 2016-01-21 08:00:00 | 73.3 |
| Orlando | 2016-01-01 08:00:00 | 72.5 |
| Miami | 2016-02-01 18:00:00 | 58.6 |
| Orlando | 2016-02-02 18:00:00 | 62.5 |
| Miami | 2016-03-03 08:00:00 | 55.6 |
| Orlando | 2016-03-03 08:00:00 | 56.7 |
| Miami | 2016-04-04 18:00:00 | 50.6 |
| Orlando | 2016-04-04 18:00:00 | 61.5 |
數(shù)據(jù)透視表應(yīng)為每個(gè)城市有一行,每個(gè)月有一列。如果你愿意,可以考慮使用相同的數(shù)據(jù)制作其他數(shù)據(jù)透視表。卷起袖子,試試吧。
到此這篇關(guān)于PostgreSQL實(shí)現(xiàn)透視表查詢(xún)的方法詳解的文章就介紹到這了,更多相關(guān)PostgreSQL透視表查詢(xún)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
postgreSQL查詢(xún)結(jié)果添加一個(gè)額外的自增序列操作
這篇文章主要介紹了postgreSQL查詢(xún)結(jié)果添加一個(gè)額外的自增序列操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02
使用python-slim鏡像遇到無(wú)法使用PostgreSQL的問(wèn)題及解決方法
這篇文章主要介紹了使用python-slim鏡像遇到無(wú)法使用PostgreSQL的問(wèn)題及解決方法,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-08-08
PostgreSQL?pg_filenode.map文件介紹
這篇文章主要介紹了PostgreSQL誤刪pg_filenode.map怎么辦,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-09-09
PostgreSQL 查看表的主外鍵等約束關(guān)系詳解
這篇文章主要介紹了PostgreSQL 查看表的主外鍵等約束關(guān)系詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
在windows下手動(dòng)初始化PostgreSQL數(shù)據(jù)庫(kù)教程
在windows下手動(dòng)初始化PG,是一件比較麻煩的事,下面我具體寫(xiě)一下過(guò)程,大家做一下參考。2014-09-09
PostgreSQL教程(十四):數(shù)據(jù)庫(kù)維護(hù)
這篇文章主要介紹了PostgreSQL教程(十四):數(shù)據(jù)庫(kù)維護(hù),本文講解了恢復(fù)磁盤(pán)空間、更新規(guī)劃器統(tǒng)計(jì)、VACUUM和ANALYZE的示例、定期重建索引等內(nèi)容,需要的朋友可以參考下2015-05-05
Postgresql排序與limit組合場(chǎng)景性能極限優(yōu)化詳解
PostgreSQL?10分區(qū)表及性能測(cè)試報(bào)告小結(jié)

