2010-07-19 2 views
38

Предположим, у меня есть эта таблицаиспользование MySQL SUM() в предложении WHERE

id | cash 
1 200 
2 301 
3 101 
4 700 

и я хочу, чтобы вернуть первую строку, в которой сумма всех предыдущих денежных средств больше, чем определенное значение:

Так, например, если я хочу вернуть первую строку, в которой сумма всех предыдущих денежных средств превышает 500, следует вернуться к строке 3

Как это сделать с помощью инструкции mysql?

использование WHERE SUM(cash) > 500 не работает

+1

Вы хотите выбрать 'ID = 3', потому что' 200 + 300> = 500' или потому, что '501> 500'? – Dolph

+0

Вы включаете предложение ORDER BY? Вы не можете сказать «следующую» запись, потому что строки не сохраняются в каком-либо конкретном порядке. – Robot

+0

это потому, что 200 + 301> = 500 ... Да, я попробовал порядок и предложения, но в этом случае они вернут строку 4, потому что строка 4> 500, а не строка 3, как предполагалось –

ответ

76

Вы можете использовать только агрегаты для сравнения в HAVING предложения:

GROUP BY ... 
    HAVING SUM(cash) > 500 

Предложение 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 

Поскольку функция агрегирования происходит в подзапрос, можно ссылаться на псевдоним столбца для него в предложении WHERE.

+0

Я думаю его редактирование разъяснило, что он имел в виду, и сделал это больше недействительным. –

+0

@ Майкл Мрозек: Thx для головы, думаю, что я понял. –

+0

привет там, спасибо за помощь Я задаюсь вопросом о том, будет ли этот код хорошо работать на большом столе, хотя Любые комментарии по затратам на производительность при использовании данного подхода на большой базе данных? –

0

При использовании агрегатных функций для фильтрации вы должны использовать оператор HAVING.

SELECT * 
FROM tblMoney 
HAVING Sum(CASH) > 500 
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 

Идея заключается в том, чтобы просуммировать все предыдущие строки, получить только те, где сумма предыдущих строк> 500, а затем пропустить один и вернуться к следующей.

+0

Это не работает, поскольку возвращается 2. Использование 'SELECT m2.id' вместо' SELECT m1.id' возвращает 3 - ожидаемый вывод. Но что, если 'id' не в порядке. Должна ли использоваться 'ORDER BY m2.id' вместо' ORDER BY m1.id'? Но предложение 'ORDER BY' делает заказ при показе вывода, правильно? Можете ли вы объяснить, как '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '', а не когда он появляется? –

3

В общем случае условие в предложении WHERE SQL-запроса может ссылаться только на одну строку. Контекст предложения WHERE оценивается до того, как какой-либо порядок был определен в предложении ORDER BY, и нет никакого неявного порядка для таблицы РСУБД.

Вы можете использовать производную таблицу для объединения каждой строки в группу строк с меньшим значением 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; 

Выход:

+----+----------+ 
| id | cash_sum | 
+----+----------+ 
| 3 |  501 | 
+----+----------+ 
+0

показывает ошибку: '# 1052 - Столбец' cash 'в списке полей неоднозначен' –

+0

@IstiaqueAhmed, спасибо, что поймал это. Я добавил имя корреляции, так что теперь это 'SUM (prev.cash)'. Это должно исправить ошибку. –

+0

И теперь он показывает 'id' как 2 вместо 3 и' cash_sum' 501.00. –

Смежные вопросы