在WHERE子句中使用mysql SUM()

kam*_*lot 45 mysql aggregate-functions having-clause

假设我有这张桌子

id | cash 
1    200
2    301
3    101
4    700
Run Code Online (Sandbox Code Playgroud)

我想要返回所有先前现金总和大于某个值的第一行:

因此,例如,如果我想要返回所有先前现金总和大于500的第一行,则应返回第3行

我如何使用mysql语句执行此操作?

使用WHERE SUM(cash) > 500 不起作用

OMG*_*ies 91

您只能在HAVING子句中使用聚合进行比较:

GROUP BY ...
  HAVING SUM(cash) > 500
Run Code Online (Sandbox Code Playgroud)

HAVING子句要求您定义GROUP BY子句.

要获得所有先前现金总和大于某个值的第一行,请使用:

SELECT y.id, y.cash
  FROM (SELECT t.id,
               t.cash,
               (SELECT SUM(x.cash)
                  FROM TABLE x
                 WHERE x.id <= t.id) AS running_total
         FROM TABLE t
     ORDER BY t.id) y
 WHERE y.running_total > 500
ORDER BY y.id
   LIMIT 1
Run Code Online (Sandbox Code Playgroud)

因为聚合函数发生在子查询中,所以可以在WHERE子句中引用它的列别名.


Bil*_*win 6

通常,WHERESQL 查询子句中的条件只能引用单行。子句的上下文WHERE在子句定义任何顺序之前进行评估ORDER BY,并且 RDBMS 表没有隐式顺序。

您可以使用派生表将每一行连接到具有较小值的行组id,并生成每个总和组的总和。然后测试总和是否满足您的标准。

CREATE TABLE MyTable ( id INT PRIMARY KEY, cash INT );

INSERT INTO MyTable (id, cash) VALUES
  (1, 200), (2, 301), (3, 101), (4, 700);

SELECT s.*
FROM (
  SELECT t.id, SUM(prev.cash) AS cash_sum
  FROM MyTable t JOIN MyTable prev ON (t.id > prev.id)
  GROUP BY t.id) AS s
WHERE s.cash_sum >= 500
ORDER BY s.id
LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

输出:

+----+----------+
| id | cash_sum |
+----+----------+
|  3 |      501 |
+----+----------+
Run Code Online (Sandbox Code Playgroud)


Eri*_*lje 5

未经测试,但我认为这将会接近?

SELECT m1.id
FROM mytable m1
INNER JOIN mytable m2 ON m1.id < m2.id
GROUP BY m1.id
HAVING SUM(m1.cash) > 500
ORDER BY m1.id
LIMIT 1,2
Run Code Online (Sandbox Code Playgroud)

想法是对所有先前的行进行求和,仅得到前一行的总和> 500的那些行,然后跳过一行并返回下一行.