Kỹ thuật này kết hợp bảng với chính nó trong một truy vấn con, nhưng nó chỉ khớp với một hàng (dựa trên contact_id và đối sánh email. Bí quyết là truy vấn con chỉ trả về một trong các địa chỉ email sử dụng MIN, về mặt lý thuyết là địa chỉ đầu tiên theo thứ tự bảng chữ cái (không đáng tin cậy, nhưng bạn đã nói điều đó không quan trọng).
Tôi đã thử nghiệm điều này với kết quả tốt.
UPDATE
email
JOIN (SELECT contact_id, MIN(email) as email
FROM email GROUP BY contact_id) as singles
USING(contact_id, email)
set is_primary=1;