0

我有一个带有销售表的数据库表t :

ID 类型 年龄
1 20
1 英国石油公司 20
1 英国石油公司 20
1 20
2 30
2 英国石油公司 30
2 英国石油公司 30
3 40

如果一个人购买了捆绑商品,则会出现捆绑销售 (TYPE B) 和不同的捆绑商品 (TYPE BP),它们都具有相同的 ID。因此,包含 2 个产品的捆绑包出现 3 次(1x TYPE B 和 2x TYPE BP)并且具有相同的 ID。

一个人还可以在单​​次销售 (TYPE P) 中购买任何其他具有相同 ID 的产品。

我需要计算客户的平均/最小/最大年龄,但每次销售的多个条目会篡改正确的计算。

实际平均年龄是

(20 + 30 + 40) / 3 = 30

并不是

(20+20+20+20 + 30+30+30 + 40) / 8 = 26,25

但我不知道如何将销售额减少到单行条目并获得 4 个需要的值?

我是否需要 GROUP BY 两次(首先按 ID,然后按 AGE?)如果是,我该怎么做?

到目前为止我的代码:

SELECT
      AVERAGE(AGE)
    , MIN(AGE)
    , MAX(AGE)
    , MEDIAN(AGE)
FROM t

但这确实计算每一行。

4

1 回答 1

4

假设所有具有相同 ID 的行的年龄相同(这本身表明存在规范化问题),您可以使用嵌套聚合

select avg(min(age)) from sales
group by id
AVG(MIN(AGE))
-------------
           30

SQL小提琴

文档中的示例非常相似;并解释为:

此计算评估由 GROUP BY 子句 (department_id) 定义的每个组的内部聚合 (MAX(salary)),并再次聚合结果。

所以对于你的版本:

此计算评估由 GROUP BY 子句 (id) 定义的每个组的内部聚合 (MIN(age)),并再次聚合结果。

内部聚合是最小值还是最大值并不重要 - 再次假设它们都相同 - 只是为每个 ID 获取一个值,然后可以对其进行平均。


您可以对原始查询中的其他值执行相同操作:

select
  avg(min(age)) as avg_age,
  min(min(age)) as min_age,
  max(min(age)) as max_age,
  median(min(age)) as med_age
from sales
group by id;
AVG_AGE MIN_AGE MAX_AGE MED_AGE
------- ------- ------- -------
     30      20      40      30

或者,如果您愿意,您可以在 CTE 或子查询中获得一次每个 ID 的值,并将第二层聚合应用于该值:

select 
  avg(age) as avg_age,
  min(age) as min_age,
  max(age) as max_age,
  median(age) as med_age
from (
   select min(age) as age
   from sales
   group by id
);

得到相同的结果。

SQL小提琴

于 2021-07-27T11:51:54.010 回答