Идентификатор таблицы запросов на основе функции агрегирования в Postgres - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть две таблицы, а именно активность и карты,

    **Activity**
+----+--------+--------+
| ID | Number | Amount |
+----+--------+--------+
|  1 |  12345 |    100 |
|  2 |  12134 |    200 |
|  3 |  12345 |    600 |
|  4 |  15647 |     50 |
|  5 |  12134 |    202 |
+----+--------+--------+

       **Cards** 
+----------+------------+
|  Number  |    Type    | 
+----------+------------+
|  12345   |  visa      |
|  12134   |  mastercard|
|  15647   |  diners    |
+----------+------------+

Я хотел бы запросить идентификатор транзакции, который имеет самую дорогую сумму среди всех транзакций, использующих карту одного типа.

+----+
| ID |
+----+
|  3 |  (ID 3 have the Highest Amount transacted on card type Visa)
|  4 |  (ID 4 have the Highest Amount transacted on card type Master)
|  5 |  (ID 5 have the Highest Amount transacted on card type diners)
+----+

Может ли это быть сделано с агрегированным запросом и без него? Мне удалось запросить тип карты и соответствующую ей наибольшую сумму, потраченную за одну транзакцию

SELECT c.Type, MAX(a.Amount) AS Highest_Transaction
       FROM Cards AS c, Activity AS a
       WHERE c.Number = a.Number
       GROUP BY c.Type

Но не уверен, как запросить только идентификатор из таблицы активности, используя «Тип» в качестве GROUP по параметру.

Ответы [ 5 ]

0 голосов
/ 14 сентября 2018

Один из подходов - использовать row_number()

SELECT
    id
  , type
  , amount
FROM (
    SELECT
        c.type
      , a.id
      , a.amount
      , ROW_NUMBER() OVER (PARTITION BY c.type ORDER BY a.amount DESC) AS rn
    FROM cards c
    JOIN activity a ON c.number = a.number
    ) d
WHERE rn = 1
0 голосов
/ 14 сентября 2018

Postgres предлагает distinct on, что очень подходит для этого запроса:

select distinct on (c.type) a.id
from cards c join
     activity a
     on c.number = a.number
order by c.type, a.amount desc;

Я включил только идентификатор активности, но вы можете включить столько столбцов, сколько хотите.

РЕДАКТИРОВАТЬ:

Если вы хотите, чтобы все строки в случае связей, то используйте функции окна:

select a.id
from (select c.type, a.id, max(a.amount) over (partition by c.type) as max_amount
      from cards c join
           activity a
           on c.number = a.number
     ) ca
where max_amount = amount;
0 голосов
/ 14 сентября 2018

К сожалению, невозможно получить правильный результат в одном запросе, поэтому вы можете рассмотреть возможность создания денормализованной временной таблицы и затем выполнить запрос, который возвращает правильный результат.

Шаг 1:

CREATE TEMPORARY TABLE tmp AS
SELECT a.ID, a.Number, a.Amount, c.Type
FROM Cards AS c
LEFT JOIN Activity AS a ON c.Number = a.Number

Шаг 2:

SELECT ID
FROM tmp AS t1
INNER JOIN (
  SELECT Type, MAX(Amount) AS Highest_Transaction
  FROM tmp
  GROUP BY Type
) AS t2 ON t1.Type = t2.Type AND t1.Amount = t2.Highest_Transaction

Результат:

 id
----
  5
  3
  4
(3 rows)

Вы можете проверить эти запросы в sqlfiddle .

0 голосов
/ 14 сентября 2018

Если Type не уникален в вашей таблице cards, вы можете сначала присоединиться к нему и сгруппировать по Type, как вы предложили:

SELECT (array_agg(activity.ID ORDER BY activity.Amount DESC))[1] AS id
FROM activity
LEFT JOIN cards ON activity.Number = cards.Number
GROUP BY cards.Type;

Обходной путь - построить упорядоченный массив длякаждую карту, но просто выберите самую высокую id.

0 голосов
/ 14 сентября 2018

Вы можете попробовать ниже запрос -

SELECT ID
FROM activity a
INNER JOIN (SELECT Num, MAX(Amount) Amt
            FROM activity
            GROUP BY Num) amt
ON a.Amount = amt.Amt;

Вот скрипка - https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=31859b70c7b532ffe5b33de0c1f2cd88

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...