我有一个类似这样的User表:
| ID | DONATION | RANK |
| 4 | 10 | 12 |
| 9 | 20 | 8 |
| 2 | 40 | 5 |
| 3 | 80 | 2 |
我想构造一个查询,在这个查询中,我检索捐赠总额小于100的用户的数量,按排名排序…例如(显然不正确):
select count(*) where sum(donation) < 100 order by rank
如果可能的话,我不知道该怎么做。我都不确定我的做法是否正确。有什么想法或建议吗?
WHERE仅适用于列或表达式,如果您想使用聚合函数(如SUM)进行过滤,则必须使用HAVING。例如:
SELECT COUNT(*)
FROM your_table
HAVING SUM(donation) < 100
如果没有有效的GROUP BY,这个查询就没有意义,但是你明白了:使用HAVING来过滤聚合函数。从技术上讲,您应该按用户id分组,然后进行计数,并对计数求和。
假设您有以下捐赠表(我认为您的ID列指向一个用户,但我不能确定):
| ID | UserId | Donation |
| 1 | 1 | 60 |
| 2 | 1 | 35 |
| 3 | 2 | 70 |
| 4 | 2 | 40 |
| 5 | 3 | 90 |
下面的查询将为您提供用户数量及其捐赠总额
SELECT COUNT(1)
FROM (
SELECT UserId
FROM Donations
GROUP BY UserId
HAVING SUM(Donation) < 100
) AS t
基于额外信息更新。
我不相信您可以从一条SQL语句中得到您想要的东西,您需要做的是创建一个游标,以循环您想要的记录(以适当的顺序),将id插入到临时表中,并维护所有的捐款。当总数超过限制时,跳出游标循环并返回结果。像这样:
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;
SELECT id, sum(donation) AS totalDonation
FROM TableName
GROUP BY id
HAVING totalDonation < 100