POSTGRESQL交叉表的实现

这里我来演示下在POSTGRESQL里面如何实现交叉表的展示,至于什么是交叉表,我就不多说了,度娘去哦。
原始表数据如下:

t_girl=# select * from score;
 name  | subject | score
-------+---------+-------
 Lucy  | English |   100
 Lucy  | Physics |    90
 Lucy  | Math    |    85
 Lily  | English |    95
 Lily  | Physics |    81
 Lily  | Math    |    84
 David | English |   100
 David | Physics |    86
 David | Math    |    89
 Simon | English |    90
 Simon | Physics |    76
 Simon | Math    |    79
(12 rows)

Time: 2.066 ms

想要实现以下的结果:

 name  | English | Physics | Math
-------+---------+---------+------
 Simon |      90 |      76 |   79
 Lucy  |     100 |      90 |   85
 Lily  |      95 |      81 |   84
 David |     100 |      86 |   89

大致有以下几种方法:

1、用标准SQL展现出来

t_girl=# select name,
t_girl-#  sum(case when subject = ‘English‘ then score else 0 end) as "English",
t_girl-#  sum(case when subject = ‘Physics‘ then  score else 0 end) as "Physics",
t_girl-#  sum(case when subject = ‘Math‘   then score else 0 end) as "Math"
t_girl-#  from score
t_girl-#  group by name order by name desc;
 name  | English | Physics | Math
-------+---------+---------+------
 Simon |      90 |      76 |   79
 Lucy  |     100 |      90 |   85
 Lily  |      95 |      81 |   84
 David |     100 |      86 |   89
(4 rows)

Time: 1.123 ms

2、用PostgreSQL 提供的第三方扩展 tablefunc 带来的函数实现
以下函数crosstab 里面的SQL必须有三个字段,name, 分类以及分类值来作为起始参数,必须以name,分类值作为输出参数。

t_girl=# SELECT *
FROM crosstab(‘select name,subject,score from score order by name desc‘,$$values (‘English‘::text),(‘Physics‘::text),(‘Math‘::text)$$)
AS score(name text, English int, Physics int, Math int);
 name  | english | physics | math
-------+---------+---------+------
 Simon |      90 |      76 |   79
 Lucy  |     100 |      90 |   85
 Lily  |      95 |      81 |   84
 David |     100 |      86 |   89
(4 rows)

Time: 2.059 ms


3、用PostgreSQL 自身的聚合函数实现

t_girl=# select name,split_part(split_part(tmp,‘,‘,1),‘:‘,2) as "English",
t_girl-# split_part(split_part(tmp,‘,‘,2),‘:‘,2) as "Physics",
t_girl-# split_part(split_part(tmp,‘,‘,3),‘:‘,2) as "Math"
t_girl-# from
t_girl-# (
t_girl(# select name,string_agg(subject||‘:‘||score,‘,‘) as tmp from score group by name order by name desc
t_girl(# ) as T;
 name  | English | Physics | Math
-------+---------+---------+------
 Simon | 90      | 76      | 79
 Lucy  | 100     | 90      | 85
 Lily  | 95      | 81      | 84
 David | 100     | 86      | 89
(4 rows)

Time: 2.396 ms


4、 存储函数实现

create or replace function func_ytt_crosstab_py ()
returns setof ytt_crosstab
as
$ytt$
  for row in plpy.cursor("select name,string_agg(subject||‘:‘||score,‘,‘) as tmp from score group by name order by name desc"):
      a = row[‘tmp‘].split(‘,‘)
      yield (row[‘name‘],a[0].split(‘:‘)[1],a[1].split(‘:‘)[1],a[2].split(‘:‘)[1])
$ytt$ language plpythonu;

t_girl=# select name,english,physics,math from  func_ytt_crosstab_py();
 name  | english | physics | math
-------+---------+---------+------
 Simon | 90      | 76      | 79
 Lucy  | 100     | 90      | 85
 Lily  | 95      | 81      | 84
 David | 100     | 86      | 89
(4 rows)

Time: 2.687 ms

5、 用PLPGSQL来实现

t_girl=# create type ytt_crosstab as (name text, English text, Physics text, Math text);
CREATE TYPE
Time: 22.518 ms

create or replace function func_ytt_crosstab ()
returns setof ytt_crosstab
as
$ytt$
  declare v_name text := ‘‘;
                v_english text := ‘‘;
		v_physics text := ‘‘;
		v_math text := ‘‘;
		v_tmp_result text := ‘‘;
  declare cs1 cursor for select name,string_agg(subject||‘:‘||score,‘,‘) from score group by name order by name desc;
begin
  open cs1;
  loop
    fetch cs1 into v_name,v_tmp_result;
    exit when not found;
    v_english = split_part(split_part(v_tmp_result,‘,‘,1),‘:‘,2);
    v_physics = split_part(split_part(v_tmp_result,‘,‘,2),‘:‘,2);
    v_math = split_part(split_part(v_tmp_result,‘,‘,3),‘:‘,2);
    return query select v_name,v_english,v_physics,v_math;
  end loop;
end;
$ytt$ language plpgsql;

t_girl=# select name,English,Physics,Math from func_ytt_crosstab();
 name  | english | physics | math
-------+---------+---------+------
 Simon | 90      | 76      | 79
 Lucy  | 100     | 90      | 85
 Lily  | 95      | 81      | 84
 David | 100     | 86      | 89
(4 rows)

Time: 2.127 ms
时间: 2024-08-29 21:16:28

POSTGRESQL交叉表的实现的相关文章

【原创】POSTGRESQL交叉表的实现

这里我来演示下在POSTGRESQL里面如何实现交叉表的展示,至于什么是交叉表,我就不多说了,度娘去哦. 原始表数据如下: t_girl=# select * from score;  name  | subject | score  -------+---------+-------  Lucy  | English |   100  Lucy  | Physics |    90  Lucy  | Math    |    85  Lily  | English |    95  Lily 

DevExpress XtraReports 入门六 控件以程序方式创建一个 交叉表 报表

原文:DevExpress XtraReports 入门六 控件以程序方式创建一个 交叉表 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助更多的人不会像我这样浪费时间才写的这篇文章,高手不想的看请路过 本文内容来DevExpress XtraReports帮助文档,如看过类似的请略过. 废话少说 开始正事 在继续本示例之前,要把所有 必需的程序集 添加到项目的 引用 列表中,并且把一个按钮拖放到窗体上. 然后,以下列方式接管此按钮的

DevExpress XtraReports 入门五 创建交叉表报表

原文:DevExpress XtraReports 入门五 创建交叉表报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助更多的人不会像我这样浪费时间才写的这篇文章,高手不想的看请路过 本文内容来DevExpress XtraReports帮助文档,如看过类似的请略过. 废话少说 开始正事 一.准备数据绑定 XRPivotGrid 控件 启动 MS Visual Studio (2005.2008 或 2010),并且新建一个或者打开一个现

JasperReport报表开发之转置交叉表

使用Jasper或BIRT等报表工具时,常会碰到一些非常规的统计,用报表工具本身或SQL都难以处理,比如源数据不符合交叉表的要求,需要转置后再呈现.集算器具有结构化强计算引擎,集成简单,可以协助报表工具方便地实现此类需求.下面通过一个例子来说明转置交叉表的实现过程. 数据库表booking汇总着各年度商品的预定数据,有四个字段,包括年份和三种预定状态,部分数据如下: 报表要求呈现指定年份及上一年的预定情况,其中行组有三项,即三种预定状态,列组是年份,测度是当年的预定数据.此外要汇总出指定年份各预

交叉表、行列转换和交叉查询经典

交叉表.行列转换和交叉查询经典分类: SqlServer 2007-12-05 16:01 6776人阅读 评论(1) 收藏 举报sqlsqlserverinsertnull产品sql server交叉表.行列转换和交叉查询经典一.什么是交叉表“交叉表”对象是一个网格,用来根据指定的条件返回值.数据显示在压缩行和列中.这种格式易于比较数据并辨别其趋势.它由三个元素组成: 行列摘要字段“交叉表”中的行沿水平方向延伸(从一侧到另一侧).在上面的示例中,“手套”(Gloves) 是一行.“交叉表”中的

报表引擎交叉表的报表设计示例

使用Delphi开发了一个报表引擎,以下是一个交叉表的示例: 报表引擎交叉表的报表设计示例

SPSS-多重响应-频率和交叉表案例分析(问卷调查分析)

在10.1休假前,希望跟大家讨论一下SPSS-多重响应--频率和交叉表分析,希望大家能够多提点提点 在云南电信网上营业厅做了一个关于"客户不使用电信3g业务的原因有哪些的问卷调查,问题所示: 这份问卷调查总更有35人参与,样本容量偏少,其中 1:选择 A :3G资费过高的有 14人 2:选择 B:  网络覆盖率低,信号不稳定的  15人 3:选择 C:买手机太麻烦的  15人 4:选择 D: 换手机号麻烦  15人 5:选择 E: 3G功能用处不大 9人 6:选择F: 朋友使用后,觉得不好  1

SQL交叉表

之前做货品横向展示时,有看到评论说用到交叉表. 公司最近需要给订单表做一个数据汇总的功能,同事给到一个参考SQL select * from (select COUNT(1) as 已锁定 from tbl_order where orderLock = 1) as A,(select COUNT(1) as 未锁定 from tbl_order where orderLock = 0) as B,(select COUNT(1) as 未发货 from tbl_order where Push

动态交叉表-统计每天员工生日数

(2010-8-27 记录)动态交叉表-统计每天员工生日数: 1.表结构 Emp ( id , empNo,empName,gender,birthday,deptId ) Dept(id,deptNo,deptName) 2.要点: 2.1 每月天数,计算两个月初的日期差即可: 2.2 小计和合计,利用 group by with ROLLUP 2.3 动态显示 1 号, 2 号, 3 号 -28 号, 29 号 - ,利用动态交叉表实现 3 .代码如下: /** 统计某月员工生日 */ IF