Вы хотите использовать SUM(IF())
. Вы хотите добавить значения, возвращаемые из IF
. Вы хотите, чтобы выражение IF
оценивалось для каждой отдельной строки. Затем используйте агрегат SUM
, чтобы добавить значение, возвращаемое для каждой строки.
Извлеките агрегат SUM
изнутри выражения IF
и вместо этого оберните IF
внутри SUM
.
Followup
Q Но почему SUM() внутри ПЧ не работает?
A Ну, это действительно работает. Это просто не работает так, как вы хотите, чтобы он работал.
Функция MySQL SUM
является «совокупной» функцией. Он объединяет строки вместе и возвращает одно значение.
Для выражения этой формы: IF(col='foo',SUM(numcol),0)
Что MySQL делает это агрегирование всех строк в SUM, и возвращает одно значение.
Другие базы данных будут подгонять подгонку и выдать ошибку с ссылкой на неагрегат col
в этом выражении.MySQL более снисходителен и относится к справочнику col
, как к агрегату (например, MIN (col) или MAX (col) ... работающему над группой строк и возвращающему одно значение. В этом случае MySQL выбирает единственная строка образца. (Не определена, какая строка будет выбрана в качестве строки выборки.) Таким образом, ссылка на col
выглядит как GET_VALUE_FROM_SAMPLE_ROW(col)
. После того, как агрегаты завершены, это выражение IF будет оцениваться один раз.
Если вы начинаете с этим запросом, это набор строк вы хотите работать.
SELECT s.name
, s.current_points
, a.activity_type
, a.points
, IF(a.activity_type='used_points',a.points,NULL) AS used_points
, IF(a.activity_type='added_points',a.points,NULL) AS added_points
FROM subscriptions s
JOIN activities a
ON a.subscription_id = s.id
при добавлении предложения GROUP BY, что собирается объединить некоторые из этих строк вместе. То, что вы получите для неагрегатов, - это значения из строки выборки.
Попробуйте добавить GROUP BY s.name
в запрос и посмотреть, что возвращается.
Также попробуйте добавить в некоторых агрегатов, таких как SUM (a.points)
SELECT s.name
, s.current_points
, a.activity_type
, a.points
, IF(a.activity_type='used_points',a.points,NULL) AS used_points
, IF(a.activity_type='added_points',a.points,NULL) AS added_points
, SUM(a.points) AS total_points
FROM subscriptions s
JOIN activities a
ON a.subscription_id = s.id
GROUP BY s.name
Наконец, мы можем добавить в выражениях в запросе в списке выбора:
, IF(a.activty_type='used_points',SUM(a.points),NULL) AS if_used_sum
, IF(a.activty_type='added_points',SUM(a.points),NULL) AS if_added_sum
Что мы обнаруживаем, что значение, возвращаемое из этих выражений, будет либо SUM (a.points), которое будет соответствовать total_points
, либо оно будет NULL. И мы можем увидеть значение столбца activity_type
, извлеченного из одной строки выборки для каждой группы, и мы можем видеть, что это выражение «работает», оно просто не делает то, что вы действительно хотите: для условного тест для каждой отдельной строки, возвращающий значение для точек или нуль, а затем суммируя это для группы.
Вы хотите использовать ** 'SUM (IF())' **. То есть, удалить агрегированную функцию 'SUM' из выражения' IF' и вместо этого переместить выражение 'IF' в' SUM'. Выражение IF должно работать на отдельных строках, SUM будет агрегировать значение, возвращаемое для каждой строки. – spencer7593