GROUP BY 一列,然后 GROUP BY 另一列
GROUP BY one column, then GROUP BY another column
我有一个数据库 table t 的销售额 table:
ID
类型
年龄
1
B
20
1
BP
20
1
BP
20
1
P
20
2
B
30
2
BP
30
2
BP
30
3
P
40
如果有人购买捆绑包,则会显示捆绑销售 (TYPE B) 和不同的捆绑产品 (TYPE BP),它们都具有相同的 ID。因此,包含 2 个产品的捆绑包出现了 3 次(1x TYPE B 和 2x TYPE BP)并且具有相同的 ID。
一个人还可以购买该单次销售 (TYPE P) 中的任何其他产品,该产品也具有相同的 ID。
我需要计算客户的 average/min/max 年龄,但每次销售的多个条目会影响正确的计算。
真实平均年龄是
(20 + 30 + 40) / 3 = 30
而不是
(20+20+20+20 + 30+30+30 + 40) / 8 = 26,25
但我不知道如何将销售额减少到单行条目并获得所需的 4 个值?
我是否需要 GROUP BY 两次(首先按 ID,然后按年龄?)如果是,我该怎么做?
到目前为止我的代码:
SELECT
AVERAGE(AGE)
, MIN(AGE)
, MAX(AGE)
, MEDIAN(AGE)
FROM t
但这确实计算每一行。
假设具有相同 ID 的所有行的年龄都相同(这本身表明存在规范化问题),您可以使用 nest aggregation:
select avg(min(age)) from sales
group by id
AVG(MIN(AGE))
-------------
30
文档中的示例非常相似;并解释为:
This calculation evaluates the inner aggregate (MAX(salary)) for each group defined by the GROUP BY clause (department_id), and aggregates the results again.
因此对于您的版本:
此计算计算 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
);
得到相同的结果。
我有一个数据库 table t 的销售额 table:
ID | 类型 | 年龄 |
---|---|---|
1 | B | 20 |
1 | BP | 20 |
1 | BP | 20 |
1 | P | 20 |
2 | B | 30 |
2 | BP | 30 |
2 | BP | 30 |
3 | P | 40 |
如果有人购买捆绑包,则会显示捆绑销售 (TYPE B) 和不同的捆绑产品 (TYPE BP),它们都具有相同的 ID。因此,包含 2 个产品的捆绑包出现了 3 次(1x TYPE B 和 2x TYPE BP)并且具有相同的 ID。
一个人还可以购买该单次销售 (TYPE P) 中的任何其他产品,该产品也具有相同的 ID。
我需要计算客户的 average/min/max 年龄,但每次销售的多个条目会影响正确的计算。
真实平均年龄是
(20 + 30 + 40) / 3 = 30
而不是
(20+20+20+20 + 30+30+30 + 40) / 8 = 26,25
但我不知道如何将销售额减少到单行条目并获得所需的 4 个值?
我是否需要 GROUP BY 两次(首先按 ID,然后按年龄?)如果是,我该怎么做?
到目前为止我的代码:
SELECT
AVERAGE(AGE)
, MIN(AGE)
, MAX(AGE)
, MEDIAN(AGE)
FROM t
但这确实计算每一行。
假设具有相同 ID 的所有行的年龄都相同(这本身表明存在规范化问题),您可以使用 nest aggregation:
select avg(min(age)) from sales
group by id
AVG(MIN(AGE))
-------------
30
文档中的示例非常相似;并解释为:
This calculation evaluates the inner aggregate (MAX(salary)) for each group defined by the GROUP BY clause (department_id), and aggregates the results again.
因此对于您的版本:
此计算计算 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
);
得到相同的结果。