【问题标题】:Max Row In Group By分组中的最大行数
【发布时间】:2019-04-11 19:05:34
【问题描述】:

我尝试通读了一些我找到的解决方案,但在我不确定如何调整它们以适应我自己的问题上似乎存在细微差别。

我有一个这样的交易表:

+------+-------+------------------------------+
| id   | rev_$ | product  | local_currency    |
+------+-------+------------------------------+
| 1    | 15    | shoe     | USD               |
| 2    | 10    | shirt    | USD               |
| 1    | 20    | shoe     | CAD               |
| 2    | 30    | shoe     | GBP               |
| 1    |  8    | shirt    | USD               |
| 2    | 15    | shirt    | USD               |
| 1    | 10    | shoe     | CAD               |
| 2    | 10    | shoe     | USD               |
+------+-------+------------------------------+

我想聚合表格以便

  • 我按产品获得每个 ID 的总数
  • local_currency 是用于最高单笔价值交易的货币(以及我未包括的其他字段)

所以聚合后的表格应该是这样的:

+------+-------+------------------------------+
| id   | rev_$ | product  | local_currency    |
+------+-------+------------------------------+
| 1    | 45    | shoe     | CAD               |
| 1    |  8    | shirt    | USD               |
| 2    | 25    | shirt    | USD               |
| 2    | 40    | shoe     | GBP               |
+------+-------+------------------------------+

类似问题:(1)(2)

【问题讨论】:

  • 您确定预期的输出是正确的吗?因为我看到同一个产品 ID 和产品有多种货币。
  • 是的,我希望聚合选择具有该 ID 的产品组的最高价值授予的货币。

标签: sql postgresql group-by


【解决方案1】:

您可以使用group by 计算总收入,将所有货币收集到一个数组中,然后从最高值中选择一个:

select id, 
       sum(rev_$), 
       product, 
       (array_agg(local_currency order by rev_$ desc))[1] as local_currency
from orders
group by id, product
order by id, product;

array_agg(local_currency order by rev_$ desc) 将为属于group by 定义的组的所有货币创建一个数组,按rev$ 降序排列。所以第一个元素([1])就是对应“最高单值交易”的那个

在线示例:https://rextester.com/VOK41538


另一种选择是编写一个aggregate function,它在没有数组的情况下执行此操作:

create or replace function first_agg (p_one anyelement, p_other anyelement )
  returns anyelement 
  language sql 
  immutable strict
as
$$
  select p_one;
$$;

create aggregate first_element 
(
  sfunc    = first_agg,
  basetype = anyelement,
  stype    = anyelement
);

那么你可以这样使用它:

select id, 
       sum(rev_$), 
       product, 
       first_element(local_currency order by rev_$ desc) as local_currency
from orders
group by id, product
order by id, product;

在线示例:https://rextester.com/YGRR9338

【讨论】:

  • 这很好,不知道这个array_agg
  • 我真的很喜欢这个解决方案!不过,这会是可扩展的吗?那个数组 agg 看起来很贵。
  • @riders994 您希望每个(id, product) 组合有多少行?
  • 这是我每个月需要汇总的每日数据,因此每个 (id, product, location) 组合最多 31 个。一个 id 很少有超过 1 个位置,但有些有很多。效率低下不会受到唯一ids 数量的影响吗?
  • @riders994:这意味着每个数组的条目永远不会超过 31 个,这应该不是问题。我添加了一个替代解决方案
【解决方案2】:

可以使用一些子查询

select  m2.id, sum(m2.rev_$), t2.local_currency
my_table m2
from  (
  select distinct local_currency, id  
  from my_table m1 
  inner join  (
    select  id, max(rev_$) max_rev
    from  my_table 
    group by id 
  ) t1  on t1.id = m1.id and t1.max_rev = m1.rev_$ 
) t2 ON m2.id= t2.id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-15
    • 2017-09-29
    • 2020-08-02
    • 1970-01-01
    • 2017-06-30
    • 2014-06-29
    • 2013-06-07
    • 1970-01-01
    相关资源
    最近更新 更多