我有一个与此类似的用户表:
| 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
如果可能的话,无法弄清楚如何做到这一点。甚至不确定我是否正确地采取这种方式。任何想法或指针?
答案 0 :(得分:6)
WHERE仅适用于列或表达式,如果要使用聚合函数(如SUM)进行过滤,则必须使用HAVING。例如:
SELECT COUNT(*)
FROM your_table
HAVING SUM(donation) < 100
如果没有有效的GROUP BY,这个查询就没有意义,但是你明白了这一点:使用HAVING过滤聚合函数。从技术上讲,您应该按用户ID进行分组,然后进行计数,并对计数求和。
答案 1 :(得分:2)
假设您有以下捐赠表(我认为您的ID列指向用户,我无法确定):
| ID | UserId | Donation |
| 1 | 1 | 60 |
| 2 | 1 | 35 |
| 3 | 2 | 70 |
| 4 | 2 | 40 |
| 5 | 3 | 90 |
以下查询将为您提供捐赠总额<&lt;的用户数。 100
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;
答案 2 :(得分:0)
SELECT id, sum(donation) AS totalDonation
FROM TableName
GROUP BY id
HAVING totalDonation < 100