PostgreSQL实现透视表查询

PostgreSQL 8.3版本发布时,引入了一个名为tablefunc的新扩展。这个扩展提供了一组非常有趣的函数。其中之一是交叉表函数,用于创建数据透视表。这就是我们将在本文中讨论的内容。
在这里插入图片描述

需求说明

解释此函数如何工作的最简单方法是使用带有数据透视表的示例。首先,我们将从实际角度解释我们最初的观点,然后定义所需的数据透视表。

假设我们是老师,需要统计你教所有科目的成绩(语言、音乐等),学校为你提供了记录所有评估或测试结果的系统。下面的SQL语句将显示之前加载到系统中的计算结果:

SELECT *
FROM evaluations

示例数据如下:

StudentSubjectEvaluation_resultEvaluation_day
Smith, JohnMusic7.02016-03-01
Smith, JohnMaths4.02016-03-01
Smith, JohnHistory9.02016-03-22
Smith, JohnLanguage7.02016-03-15
Smith, JohnGeography9.02016-03-04
Gabriel, PeterMusic2.02016-03-01
Gabriel, PeterMaths10.02016-03-01
Gabriel, PeterHistory7.02016-03-22
Gabriel, PeterLanguage4.02016-03-15
Gabriel, PeterGeography10.02016-03-04
  • 期望结果

下面的表格可以很容易地跟踪学生的进度。在计算机科学中,我们称这种网格为透视表。如果分析数据透视表,你会发现我们使用原始数据中的值作为列标题或字段名(在本例中是地理、历史、数学等)。

希望的数据格式如下:

StudentGeographyHistoryLanguageMathsMusic
Gabriel, Peter10.07.04.010.02.0
Smith, John9.09.07.04.07.0

启用tablefunc扩展

正如我们前面提到的,crosstab 函数是PostgreSQL扩展tablefunc的一部分。要调用crosstab 函数,必须首先通过执行以下SQL命令启用tablefunction扩展:

CREATE extension tablefunc;

crosstab 函数

crosstab 函数接收SQL SELECT命令作为参数,该参数必须符合以下限制:

  • SELECT必须返回3列。
  • SELECT中的第一列将是数据透视表或最终结果中每一行的标识符。在我们的例子中,这是学生的名字。注意学生的名字(John Smith和Peter Gabriel)是如何出现在第一列中的。
  • SELECT中的第二列表示透视表中的类别。在我们的例子中,这些类别是学校的科目。需要注意的是,该列的值将扩展到数据透视表中的许多列中。如果第二列返回5个不同的值(地理、历史等),则数据透视表将有5列。
  • SELECT中的第三列表示分配给数据透视表的每个单元格的值。这些是我们示例中的求值结果。

如果我们把数据透视表看作一个二维数组,那么第一个SELECT列是数组的第一个维度,第二个SELECT列是第二个维度,第三个是数组元素的值。比如grid [first_column_value, second_column_value] = third_column_value。

SELECT student, subject, evaluation_result FROM evaluations ORDER BY 1,2

crosstab 函数在SELECT语句的FROM子句中调用。我们必须定义将进入最终结果的列和数据类型的名称。就我们的目的而言,最终结果定义为:

AS final_result(Student TEXT, Geography NUMERIC,History NUMERIC,Language NUMERIC,Maths NUMERIC,Music NUMERIC)

整合上面的内容,完整的语句:

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);

查询结果如下:

StudentGeographyHistoryLanguageMathsMusic
Gabriel, Peter10.07.04.010.02.0
Smith, John9.09.07.04.07.0

透视表实战示例

从单个数据集,我们可以生成许多不同的数据透视表。让我们继续以教师和班级为例,看看我们的一些选项。

查询学生每月成绩

作为老师,我们可能还需要一份学生今年迄今为止的评估结果报告。例如,假设我们想要获得约翰·史密斯从3月到7月的平均评价。在如下的网格中,表格看起来是这样的:

month textgeography numerichistory numericlanguage numericmaths numericmusic numeric
39.009.007.004.007.00
44.007.507.004.005.66
58.006.007.007.007.00
67.507.007.007.008.00
76.669.007.7510.006.00

实现透视表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);

处理不完整记录

我们也可以称这一节为“交叉表的限制以及如何解决它”。在讨论这个问题之前,让我们先来设定一下场景:

假设你想看看是否有些学生在某些科目上没有考试分数。也许你可以尝试前面的查询,为July添加一个WHERE子句。代码看起来像这样:

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);

下面的数据透视表是该查询的结果。我们很快就可以看到,我们没有给彼得的语言、数学和音乐评分。

StudentGeographyHistoryLanguageMathsMusic
Gabriel, Peter10.06.07.00
Smith, John6.08.06.09.04.0

但是,如果我们尝试常规查询以获得Peter在7月份的成绩……

SELECT * from evaluations
where extract ( month from evaluation_day)=7 and student like 'Gabriel, Peter'

我们获得了不同的结果:

studentsubjectevaluation_resultevaluation_day
Gabriel, PeterLanguage6.02016-07-15
Gabriel, PeterGeography10.02016-07-04

当然,第二个查询是正确的,因为它显示的是原始数据。问题是数据透视表构建过程中,有些种类的信息缺失。为了解决这个问题,我们可以使用带有第二个参数的交叉表函数,该参数表示完整的类别列表。如果存在缺失值,数据透视表仍将正确构建。

第二个参数内容:‘select name from subject order by 1’ ,完整语句如下:

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);

现在输出结果包括缺失科目,并使用–表示:

StudentGeographyHistoryLanguageMathsMusic
Gabriel, Peter10.06.0
Smith, John6.08.06.09.04.0

练习数据

数据透视表为我们提供了一种不同的方式来查看数据。此外,我们可以使用交叉表函数基于相同的原始数据创建不同的数据透视表。尝试构建一个数据透视表,根据下表中的原始数据显示每个城市和月份的最高温度。

CREATE TABLE weather (city text, when timestamp, temperature float);
CityWhenTemperature
Miami2016-01-01 08:00:0068.6
Miami2016-01-21 08:00:0073.3
Orlando2016-01-01 08:00:0072.5
Miami2016-02-01 18:00:0058.6
Orlando2016-02-02 18:00:0062.5
Miami2016-03-03 08:00:0055.6
Orlando2016-03-03 08:00:0056.7
Miami2016-04-04 18:00:0050.6
Orlando2016-04-04 18:00:0061.5

数据透视表应为每个城市有一行,每个月有一列。如果你愿意,可以考虑使用相同的数据制作其他数据透视表。卷起袖子,试试吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/929148.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

消息中间件-Kafka1-实现原理

消息中间件-Kafka 一、kafka简介 1、概念 Kafka是最初由Linkedin公司开发,是一个分布式、支持分区(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以…

protobuf实现Hbase数据压缩

目录 前置HBase数据压缩效果获取数据(反序列化) 前置 安装说明 使用说明 HBaseDDL和DML操作 HBase数据压缩 问题 在上文的datain中原文 每次写入数据会写入4个单元格的内容,现在希望能对其进行筛减,合并成1格,减少存储空间(序列…

爬虫专栏第二篇:Requests 库实战:从基础 GET 到 POST 登录全攻略

简介:本文聚焦 Requests 库的强大功能与应用实战。首先介绍其安装步骤及版本选择要点,随后深入讲解 GET 请求,以百度页面为例,展示如何发起基本 GET 请求、巧妙添加 headers 与参数以精准搜索,以及正确设置 encoding 避…

【Leetcode】19. 删除链表的第N个节点

【Leetcode】19. 删除链表的第N个节点 1. 题目介绍2. 方法一:计算链表长度逻辑流程:代码复杂度分析 1. 题目介绍 题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1: 输入:head [1,2,…

工业齐套管理虚拟现实仿真模拟软件

工业齐套管理虚拟现实仿真模拟软件是与法国最大的汽车制造商合作开发的一款虚拟现实仿真模拟软件,借助身临其境的虚拟现实环境,无需停止生产线,即可模拟仓库和提货区域。 工业齐套管理虚拟现实仿真模拟软件不仅适用于汽车工业,安全…

【嘟嘟早教卡】 小程序源码分享带后台管理

【嘟嘟早教卡】是专门为 3-6 岁婴幼儿童学习普通话、英语研发的早教启蒙认知识字的小程序 小程序由 Taro 及 Tailwind CSS 构建而成,后台管理使用 Laravel 及 Tailwind CSS 想法源于小时候玩的认知卡片,基本大部分家庭都买过认知卡片,我按照…

概率论相关知识随记

作为基础知识的补充,随学随记,方便以后查阅。 概率论相关知识随记 期望(Expectation)期望的定义离散型随机变量的期望示例:掷骰子的期望 连续型随机变量的期望示例:均匀分布的期望 期望的性质线性性质期望的…

FastAPI 响应状态码:管理和自定义 HTTP Status Code

FastAPI 响应状态码:管理和自定义 HTTP Status Code 本文介绍了如何在 FastAPI 中声明、使用和修改 HTTP 状态码,涵盖了常见的 HTTP 状态码分类,如信息响应(1xx)、成功状态(2xx)、客户端错误&a…

oracle 11g中如何快速设置表分区的自动增加

在很多业务系统中,一些大表一般通过分区表的形式来实现数据的分离管理,进而加快数据查询的速度。分区表运维管理的时候,由于人为操作容易忘记添加分区,导致业务数据写入报错。所以我们一般通过配置脚本或者利用oracle内置功能实现…

机器学习深入剖析逻辑回归算法

一、引言 在机器学习领域,逻辑回归(Logistic Regression)是一种极为经典且应用广泛的算法。尽管其名称带有 “回归” 二字,但实际上它主要用于解决分类问题,并且在众多领域都发挥着重要作用。接下来,让我们…

如何加强游戏安全,防止定制外挂影响游戏公平性

在现如今的游戏环境中,外挂始终是一个困扰玩家和开发者的问题。尤其是定制挂(Customized Cheats),它不仅复杂且隐蔽,更能针对性地绕过传统的反作弊系统,对游戏安全带来极大威胁。定制挂通常是根据玩家的需求…

6.824/6.5840 Lab 1: MapReduce

宁静的夏天 天空中繁星点点 心里头有些思念 思念着你的脸 ——宁夏 完整代码见: https://github.com/SnowLegend-star/6.824 由于这个lab整体难度实在不小,故考虑再三还是决定留下代码仅供参考 6.824的强度早有耳闻,我终于也是到了挑战这座高…

解决Jupyter Notebook无法转化为Pdf的问题(基于Typora非常实用)

笔者在完成各项作业和做笔记时,经常用到jupyter notebook;其因为可以同时运行python并提供格式化的数字公式的输入方式,得到了广大用户的喜爱。 当我们想要将.ipynb文件导出为pdf时,有两种常用方法。 1.Ctrlp 2.通过File ->…

[在线实验]-RabbitMQ镜像的下载与部署

镜像下载 docker的rabbitmq镜像资源-CSDN文库 加载镜像 docker load --input rabbitmq.tar 给镜像打标签 这里发现镜像名为none,需要给镜像重命名下 docker tag [镜像id] [新镜像名称]:[新镜像标签] docker tag ebaf409ffbe2 rabbitmq:management 运行镜像…

【JVM】—G1 GC日志详解

G1 GC日志详解 ⭐⭐⭐⭐⭐⭐ Github主页👉https://github.com/A-BigTree 笔记链接👉https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以,麻烦各位看官顺手点个star~😊 文章目录 G1 GC日志详解1 G1 GC周期2 G1日…

ADBC 查询语法介绍:EXECUTE_QUERY

可使用 CL_SQL_STATEMENT 类的以下实例方法执行查询: EXECUTE_QUERY 该方法有一个字符串类型的强制输入参数 STATEMENT,必须向其传递语法正确的 SELECT 语句。与 DML 语句一样,SET_PARAM 方法可用于将 ABAP 数据对象绑定到占位符。 查询结…

线程信号量 Linux环境 C语言实现

既可以解决多个同类共享资源的互斥问题&#xff0c;也可以解决简易的同步问题 头文件&#xff1a;#include <semaphore.h> 类型&#xff1a;sem_t 初始化&#xff1a;int sem_init(sem_t *sem, int pshared, unsigned int value); //程序中第一次对指定信号量调用p、v操…

springboot+mybatis对接使用postgresql中PostGIS地图坐标扩展类型字段

方案一&#xff08;完全集成和自动解析&#xff09;&#xff1a; <dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId></dependency> 使用 org.postgresql.geometric包下的 PGpoint 类来接收数据库中POINT…

21个Python脚本自动执行日常任务(1)

引言 作为编程领域摸爬滚打超过十年的老手&#xff0c;我深刻体会到&#xff0c;自动化那些重复性工作能大大节省我们的时间和精力。 Python以其简洁的语法和功能强大的库支持&#xff0c;成为了编写自动化脚本的首选语言。无论你是专业的程序员&#xff0c;还是希望简化日常工…

【Python网络爬虫笔记】6- 网络爬虫中的Requests库

一、概述 Requests 是一个用 Python 语言编写的、简洁且功能强大的 HTTP 库。它允许开发者方便地发送各种 HTTP 请求&#xff0c;如 GET、POST、PUT、DELETE 等&#xff0c;并且可以轻松地处理请求的响应。这个库在 Python 生态系统中被广泛使用&#xff0c;无论是简单的网页数…