我写了一个查询,其中一列是一个月.从中我得到了最小月、最大月和中值月.下面是我的问题.

select ext.employee,
       pl.fromdate,
       ext.FULL_INC as full_inc,
       prevExt.FULL_INC as prevInc,
       (extract(year from age (pl.fromdate))*12 +extract(month from age (pl.fromdate))) as month,
       case
         when prevExt.FULL_INC is not null then (ext.FULL_INC -coalesce(prevExt.FULL_INC,0))
         else 0
       end as difference,
       (case when prevExt.FULL_INC is not null then (ext.FULL_INC - prevExt.FULL_INC) / prevExt.FULL_INC*100 else 0 end) as percent
from pl_payroll pl
  inner join pl_extpayfile ext
          on pl.cid = ext.payrollid
         and ext.FULL_INC is not null
  left outer join pl_extpayfile prevExt
               on prevExt.employee = ext.employee
              and prevExt.cid = (select max (cid) from pl_extpayfile
                                 where employee = prevExt.employee
                                 and   payrollid = (
                                   select max(p.cid)
                                   from pl_extpayfile,
                                        pl_payroll p
                                   where p.cid = payrollid
                                   and   pl_extpayfile.employee = prevExt.employee
                                   and   p.fromdate < pl.fromdate
                                 )) 
              and coalesce(prevExt.FULL_INC, 0) > 0 
where ext.employee = 17 
and (exists (
    select employee
    from pl_extpayfile preext
    where preext.employee = ext.employee
    and   preext.FULL_INC <> ext.FULL_INC
    and   payrollid in (
      select cid
      from pl_payroll
      where cid = (
        select max(p.cid)
        from pl_extpayfile,
             pl_payroll p
        where p.cid = payrollid
        and   pl_extpayfile.employee = preext.employee
        and   p.fromdate < pl.fromdate
      )
    )
  )
  or not exists (
    select employee
    from pl_extpayfile fext,
         pl_payroll p
    where fext.employee = ext.employee
    and   p.cid = fext.payrollid
    and   p.fromdate < pl.fromdate
    and   fext.FULL_INC > 0
  )
)
order by employee,
         ext.payrollid desc

如果不可能,那么可以得到最大月数和最小月数吗?

推荐答案

您需要名为minmax的聚合函数.请参阅PostgreSQL文档和教程:

PostgreSQL中没有内置的中间值,但是已经实现了一个中间值并将其贡献给了wiki:

http://wiki.postgresql.org/wiki/Aggregate_Median

加载后,它的使用方式与minmax相同.用PL/PgSQL编写会稍微慢一点,但如果速度至关重要,甚至还有一个C版本可以进行调整.

UPDATE comments 后:

这听起来像是你想在显示单个结果的同时显示统计汇总.使用普通聚合函数无法做到这一点,因为无法引用结果列表中GROUP BY以外的列.

您需要从子查询中获取统计信息,或者将聚合用作窗口函数.

给定虚拟数据:

CREATE TABLE dummystats ( depname text, empno integer, salary integer );
INSERT INTO dummystats(depname,empno,salary) VALUES
('develop',11,5200),
('develop',7,4200),
('personell',2,5555),
('mgmt',1,9999999);

... 加the median aggregate from the PG wiki后:

您可以使用普通骨料进行此操作:

regress=# SELECT min(salary), max(salary), median(salary) FROM dummystats;
 min  |   max   |         median          
------+---------+----------------------
 4200 | 9999999 | 5377.5000000000000000
(1 row)

但不是这个:

regress=# SELECT depname, empno, min(salary), max(salary), median(salary)
regress-# FROM dummystats;
ERROR:  column "dummystats.depname" must appear in the GROUP BY clause or be used in an aggregate function

因为在聚合模型中,将平均值与单个值一起显示是没有意义的.您可以显示组:

regress=# SELECT depname, min(salary), max(salary), median(salary) 
regress-# FROM dummystats GROUP BY depname;
  depname  |   min   |   max   |          median          
-----------+---------+---------+-----------------------
 personell |    5555 |    5555 | 5555.0000000000000000
 develop   |    4200 |    5200 | 4700.0000000000000000
 mgmt      | 9999999 | 9999999 |  9999999.000000000000
(3 rows)

... 但听起来你想要的是个人价值观.为此,必须使用window,这是PostgreSQL 8.4中新增的功能.

regress=# SELECT depname, empno, 
                 min(salary) OVER (), 
                 max(salary) OVER (), 
                 median(salary) OVER () 
          FROM dummystats;

  depname  | empno | min  |   max   |        median         
-----------+-------+------+---------+-----------------------
 develop   |    11 | 4200 | 9999999 | 5377.5000000000000000
 develop   |     7 | 4200 | 9999999 | 5377.5000000000000000
 personell |     2 | 4200 | 9999999 | 5377.5000000000000000
 mgmt      |     1 | 4200 | 9999999 | 5377.5000000000000000
(4 rows)

另见:

Postgresql相关问答推荐

如何在gorm中创建一个可读但不可写的字段

当通过PostgreSQL FDW中的视图使用时,年龄函数的计算方式不同

Postgres将唯一索引添加到已在分区上具有PK的分区表中,然后添加PK

多克.波斯格雷斯.PgAdmin4

在PostgreSQL中,`MY_VARIABLE IN(<;Long_ARRAY_of_Items>;)`何时是FAST?

Postgres如何插入带有十进制逗号的实数?

select语句的Jooq代码生成

将具有自定义类型的表从一种模式复制到另一种模式

在插入时创建一个触发器,在PostgreSQL中的另一个表上创建另一个触发器

为什么 Postgres 中的 now() 和 now()::timestamp 对于 CET 和 CEST 时区如此错误?

supabase 中的交易

Postgres数据库系统已准备好接受连接和docker compose

postgres hierarchy - 用祖先的值填充缺失值

使用正则表达式计算 SQL 查询中 WHERE 过滤器的数量

@符号在yacc中的函数中是什么意思

计算每行的多列中的非 NULL 元素

将一列与另一列的每个元素进行比较,该列是一个数组

postgres 和 python

在 Spring Boot 应用程序中禁用表重新创建

仅在存在时重命名列