【问题标题】:Average sum based on condition基于条件的平均总和
【发布时间】:2018-12-17 10:58:13
【问题描述】:

我在 Postgres 数据库中有这个表和数据样本

CREATE TABLE testAAA(Id integer PRIMARY KEY, datum date, COLA text, COLB text, COLC text, COLD int);

/* Create few records in this table */
INSERT INTO testAAA VALUES(1,to_date('01/01/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','1');
INSERT INTO testAAA VALUES(2,to_date('01/02/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','1');
INSERT INTO testAAA VALUES(3,to_date('01/03/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','1');
INSERT INTO testAAA VALUES(4,null,'PLANTA','VENDORA','OPA','1');
INSERT INTO testAAA VALUES(5,to_date('01/10/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','5');
INSERT INTO testAAA VALUES(6,to_date('01/10/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','10');
INSERT INTO testAAA VALUES(7,to_date('01/11/2018','dd/mm/yyyy'),'PLANTA','VENDORB','OPA','50');
INSERT INTO testAAA VALUES(8,to_date('01/10/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','10');
INSERT INTO testAAA VALUES(9,to_date('01/11/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPB','5');
COMMIT;

我正在尝试根据条件和组合计算平均总和:

SELECT COLA,COLB,COLC,
CASE
  WHEN (datum >= now() - interval '6 month') THEN SUM(COLD)/6
  ELSE '0'
END AS datum_range
FROM testAAA
group by COLA,COLB,COLC;

我的目标是使用 COLA+COLB+COLC 的组合在 COLD 列上生成过去 6 个月的平均值,如果满足 DATE 间隔条件,则跳过空值。

现在我收到此错误:

Error(s), warning(s):

42803: column "testaaa.datum" must appear in the GROUP BY clause or be used in an aggregate function

如何解决上述错误?

【问题讨论】:

  • 请为您的输入数据添加预期输出

标签: postgresql average


【解决方案1】:

demo:db<>fiddle

SELECT *,
    SUM(COLD) FILTER (WHERE datum >= now() - interval '6 month') OVER (PARTITION BY COLA, COLB, COLC) / 6.0 as avg
FROM testAAA

结果:

| id |      datum |   cola |    colb | colc | cold |                avg |
|----|------------|--------|---------|------|------|--------------------|
|  1 | 2018-01-01 | PLANTA | VENDORA |  OPA |    1 |  4.166666666666667 |
|  2 | 2018-02-01 | PLANTA | VENDORA |  OPA |    1 |  4.166666666666667 |
|  3 | 2018-03-01 | PLANTA | VENDORA |  OPA |    1 |  4.166666666666667 |
|  4 |     (null) | PLANTA | VENDORA |  OPA |    1 |  4.166666666666667 |
|  5 | 2018-10-01 | PLANTA | VENDORA |  OPA |    5 |  4.166666666666667 |
|  6 | 2018-10-01 | PLANTA | VENDORA |  OPA |   10 |  4.166666666666667 |
|  8 | 2018-10-01 | PLANTA | VENDORA |  OPA |   10 |  4.166666666666667 |
|  9 | 2018-11-01 | PLANTA | VENDORA |  OPB |    5 | 0.8333333333333334 |
|  7 | 2018-11-01 | PLANTA | VENDORB |  OPA |   50 |  8.333333333333334 |

[demo: dbfiddle][4]

  1. 使用window function SUM(...) OVER (PARTITION BY ...) 允许您像在GROUP 子句中一样进行SUM 聚合,但保留原始行。聚合作为单独的列添加。
  2. FILTER 子句允许您过滤聚合函数的输入。所以你只能聚合datum &gt;= ... 的行

【讨论】:

  • 谢谢,但是如果我想在源表的所有 9 条记录中保留 avg 作为输出?
  • @user3925023 展开答案
  • 谢谢,但我的期望是看到所有这些记录 havin PLANTA |文朵拉 | OPA AVG = 4.83
  • 4.83 是我的错,当然是 4.16667。但是对于您的情况,您只需要删除 CASE。附加答案。下次请在您的问题中提供预期的输出。然后你会更快地得到正确的答案:)
【解决方案2】:

为什么不把条件移到where 子句:

SELECT   cola, colb, colc, SUM(cold) / 6
FROM     testAAA
WHERE    datum >= NOW() - INTERVAL '6 MONTH' 
GROUP BY cola, colb, colc

【讨论】:

  • 我需要保留所有记录,如果这样做,我会删除条件无效的记录
猜你喜欢
  • 1970-01-01
  • 2016-01-18
  • 2023-03-18
  • 2021-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-31
  • 2016-09-07
相关资源
最近更新 更多