I have User and Coupon and I want that whenever a user views a coupon, I will insert the data into a coupon_user table if the user hasn't already done viewed this coupon before - insert if not exist.
How would you go about doing this with the least queries possible?
You could either get the current ids, then sync or you could run a query to see if the relationship currently exists and only add the relationship if it currently doesn't exist. If you're only saving a single coupon I'd choose the latter approach.
->sync(...) accepts a second parameter that tells it not to detach related models not being synced. If you look in the source code it will do basically the same thing then you described (list current, diff, attach new)
For your code this should do it:
// note the false boolean as the second parameter, it will skip detaching (e.g. deleting)
// ids not being synced
$user->coupons()->sync($coupon_id, false);