Так не получилось, но я подставил вместо ( SELECT MAX(d) FROM msg ) NOW() и все заработало, в принципе меня и так устроит) Спасибо очень помогли) 2 дня не мог понять как записать этот запрос)
NOW() возвращает текущую дату, это слегка противоречит постановке задачи. А не работало, потому что подзапрос надо было использовать как скалярное значение, обернув в скобки:
DELETE FROM msg WHERE d <= DATE_SUB((SELECT MAX(d) FROM msg), INTERVAL 30 MINUTE);