【问题标题】:How can I get the median value of each product in Postgresql?如何获得 Postgresql 中每个产品的中值?
【发布时间】:2019-11-16 04:25:32
【问题描述】:

我有一张名为“sales”的表。

create table sales
    (
        cust    varchar(20),
        prod    varchar(20),
        day integer,
        month   integer,
        year    integer,
        state   char(2),
        quant   integer
    );
insert into sales values ('Bloom', 'Pepsi', 2, 12, 2001, 'NY', 4232);
insert into sales values ('Knuth', 'Bread', 23, 5, 2005, 'PA', 4167);
insert into sales values ('Emily', 'Pepsi', 22, 1, 2006, 'CT', 4404);
insert into sales values ('Emily', 'Fruits', 11, 1, 2000, 'NJ', 4369);
insert into sales values ('Helen', 'Milk', 7, 11, 2006, 'CT', 210);
insert into sales values ('Emily', 'Soap', 2, 4, 2002, 'CT', 2549);
insert into sales values ('Bloom', 'Eggs', 30, 11, 2000, 'NJ', 559);

.... 总共有 498 行。以下是该表的概述:

现在我想获得每种产品的中位数数量。结果表应如下所示:

我已经尝试了这些代码并且它有效:

CREATE OR REPLACE FUNCTION _final_median(NUMERIC[])
   RETURNS NUMERIC AS
$$
   SELECT AVG(val)
   FROM (
     SELECT val
     FROM unnest($1) val
     ORDER BY 1
     LIMIT  2 - MOD(array_upper($1, 1), 2)
     OFFSET CEIL(array_upper($1, 1) / 2.0) - 1
   ) sub;
$$
LANGUAGE 'sql' IMMUTABLE;

CREATE AGGREGATE median(NUMERIC) (
  SFUNC=array_append,
  STYPE=NUMERIC[],
  FINALFUNC=_final_median,
  INITCOND='{}'
);


SELECT prod,round(median(quant)) AS median_quant FROM sales
group by prod
order by prod;

但我想使用“聚合”函数来获得相同的结果,如果有的话我可以在没有特殊函数的情况下做到这一点?

【问题讨论】:

    标签: sql database postgresql group-by aggregation


    【解决方案1】:

    中位数是第 0.5 个百分位数(值在有序集合的中间)。你可以使用percentile_cont来计算:

    select percentile_cont(0.50) within group (order by sales.quant)
    from sales
    

    【讨论】:

    • 是的,它有效。但是无论如何我可以在不使用特殊功能的情况下做到这一点吗?就像在“组”之外写一个聚合函数?
    • @WikizVito 为什么是特殊功能?我没有关注。
    • 嗯,意思是反正有这样写一个函数,用With函数把它们组合起来,而不是直接用这个percentile_cont??
    • 我还是不知道。这实际上与您提供的结果相同......
    • 创建或替换函数 _final_median(NUMERIC[]) 返回数字为 $$ SELECT AVG(val) FROM ( SELECT val FROM unnest($1) val ORDER BY 1 LIMIT 2 - MOD(array_upper($1, 1), 2) 偏移 CEIL(array_upper($1, 1) / 2.0) - 1 ) 子; $$ LANGUAGE 'sql' 不可变;您有什么想法可以将其转换为可理解的查询并使用 WITH 函数将其组合起来吗?
    【解决方案2】:

    似乎聚合函数试图找到上中位数。

    在这种情况下,可以使用降序的 PERCENTILE_DISC(0.5) 进行聚合。

    select prod, 
     count(*) as total_prod, 
     percentile_disc(0.5) within group (order by quant desc) as ceil_median_quant
    from sales
    group by prod;
    

    对 rextester 的测试here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 2010-11-24
      • 2021-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多