Reputation: 35
I have a User table similar to this:
| ID | DONATION | RANK |
| 4 | 10 | 12 |
| 9 | 20 | 8 |
| 2 | 40 | 5 |
| 3 | 80 | 2 |
I would like to construct a query where I retrieve the number of users where the combined sum of the donations is less than say 100, ordered by rank... something like (obviously not correct):
select count(*) where sum(donation) < 100 order by rank
Can't figure out how to do this if it's even possible. Not even sure I'm going about this the right way. Any ideas or pointers?
Upvotes: 1
Views: 2413
Reputation: 150
Assuming you have the following Donation table (as much as I think your ID column points to a user, I could not be sure):
| ID | UserId | Donation |
| 1 | 1 | 60 |
| 2 | 1 | 35 |
| 3 | 2 | 70 |
| 4 | 2 | 40 |
| 5 | 3 | 90 |
The the following query will give you the number of users with their total donation < 100
SELECT COUNT(1)
FROM (
SELECT UserId
FROM Donations
GROUP BY UserId
HAVING SUM(Donation) < 100
) AS t
Update based on extra information.
I do not believe you can get what you want from a single SQL statement, what you would need to do is create a cursor that loops around the records you want (in appropiate order) inserting the id into a temp table, and maintaining a total of the donations. When the total is above your limit, break out of the cursor loop and return the results. Something like this:
CREATE PROCEDURE GetTopDontations( limit DECIMAL(...) )
BEGIN
CREATE TEMPORARY TABLE t1 (
id INT
);
DECLARE total, Donation DECIMAL(...);
DECLARE Id INT;
DECLARE curDonations CURSOR FOR SELECT ID, Dontaion FROM Donations ORDER BY <something relevant>;
SET total = 0.0;
OPEN curDonations;
read_loop: LOOP
FETCH curDonations INTO Id, Donation;
INSERT INTO t1( id ) VALUES ( Id );
SET total = total + Donation;
IF( total > limit ) THEN
LEAVE read_loop;
END IF;
END LOOP:
CLOSE curDonations;
SELECT d.*
FROM Donations d
INNER JOIN t1
ON d.Id = t1.Id;
END;
Upvotes: 2
Reputation: 35927
WHERE only works for columns or expressions, if you want to filter with an aggregate function (like SUM), you have to use HAVING. For example :
SELECT COUNT(*)
FROM your_table
HAVING SUM(donation) < 100
This query doesn't really make sense without a valid GROUP BY, but you get the point: use HAVING to filter with an aggregate function. Technically, you should group by user id then do the count, and sum the count.
Upvotes: 6
Reputation: 23894
SELECT id, sum(donation) AS totalDonation
FROM TableName
GROUP BY id
HAVING totalDonation < 100
Upvotes: 0