Ваш запрос неправильно использует COUNT, который был покрыт @ Will A's answer .
Я также хотел бы предложить, возможно, лучшую конструкцию альтернативы, которая, я думаю, отражает ту же логику:
SELECT
c.name,
c.address,
c.postcode,
c.dob,
c.mobile,
c.email,
COUNT(*) AS purchased,
COUNT(b.the_date > $now OR NULL) AS remaining
FROM customers AS c
INNER JOIN bookings AS b ON b.id_customer = c.id
GROUP BY c.id
ORDER BY c.name ASC
Примечание. Обычно ожидается, что вы включите все неагрегированные выражения SELECT в GROUP BY. Однако MySQL поддерживает сокращенные списки GROUP BY , поэтому достаточно указать ключевые выражения, которые однозначно идентифицируют все неагрегированные данные, которые вы извлекаете. Пожалуйста, избегайте произвольного использования этой функции . Если столбец, не включенный в GROUP BY, имеет более одного значения на группу, вы не можете контролировать , какое значение будет фактически возвращено при извлечении этого столбца без агрегирования .