Макс Роу в группе по - PullRequest
       27

Макс Роу в группе по

3 голосов
/ 11 апреля 2019

Я попытался прочитать ряд найденных решений, но, похоже, есть небольшие различия в проблемах, когда я не уверен, как адаптировать их под свои собственные.

У меня есть таблица транзакций, подобная следующей:

+------+-------+------------------------------+
| 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               |
+------+-------+------------------------------+

Я хочу агрегировать таблицу так, чтобы

  • Я получил сумму для каждого идентификатора по продукту
  • 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)

Ответы [ 2 ]

4 голосов
/ 11 апреля 2019

Вы можете использовать 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


Другой вариант - написать агрегатная функция , которая делает это без массива:

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

1 голос
/ 11 апреля 2019

может использовать некоторый подзапрос

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...