1

I ran in to this problem on a CS question site, and I can't figure out how to do this.

Problem

My first solution ran in to a dead end with this code

SELECT 
 recipient
FROM 
 transfers
GROUP BY
 recipient
HAVING
 sum(amount) >= 1024
ORDER BY
 recipient ASC;

But there is no way to put a limit on the sum to sum the largest 3 values.

Another idea was to create a subquery and join the two tables.

like so

SELECT
recipient,
(   SELECT SUM(amount)
    FROM transfer t1
    WHERE t1.recipient = t.recipient ORDER BY amount DESC LIMIT 3) as summedValue
FROM
transfer t

However, that summed all the values and not just the top three also.

CL.
  • 173,858
  • 17
  • 217
  • 259
Jonathan
  • 53
  • 1
  • 1
  • 6

1 Answers1

0

For one specific recipient, the following query gets the (at most) three largest transfers:

SELECT *
FROM transfers
WHERE recipient = ?
ORDER BY amount DESC
LIMIT 3;

To get the entire amount of these transfers, wrap this into a subquery (otherwise, the LIMIT would be executed after the aggregation):

SELECT sum(amount)
FROM (SELECT *
      FROM transfers
      WHERE recipient = ?
      ORDER BY amount DESC
      LIMIT 3);

Then use that to filter the accounts (the DISTINCT subquery ensures that each account is checked only once):

SELECT recipient
FROM (SELECT DISTINCT recipient
      FROM transfers) AS r
WHERE (SELECT sum(amount)
       FROM (SELECT *
             FROM transfers
             WHERE recipient = r.recipient
             ORDER BY amount DESC
             LIMIT 3)
      ) >= 1024;
CL.
  • 173,858
  • 17
  • 217
  • 259
  • Thank you very much. Could you explain to me the difference between using group by/having and where? – Jonathan Mar 28 '17 at 19:10
  • HAVING is executed after the aggregation, WHERE, before. But my answer uses subqueries to control the execution order. – CL. Mar 28 '17 at 20:49