This condition filters all not null match of rent
AND DATE_FORMAT( `Rent`.`month` , '%Y-%m' ) <> DATE_FORMAT( NOW( ) , '%Y-%m' )
While this condition filters all null match of rent
AND `Rent`.`id` IS NULL
The first condition doesn't seem to meet any of your initial requirements and basically this: - that have NO matched record from rents.
I will try to remove first condition from where clause.
edited after comment: A way that I prefer to write condition of no match is using the exists operator in this manner:
SELECT `Contract`.*
FROM `contracts` AS `Contract`
WHERE
Contract`.`active` = 1
AND `Contract`.`end_date` > NOW( )
AND `Contract`.`start_date` < NOW( )
AND NOT EXISTS (
SELECT * FROM `rents` AS `Rent`
WHERE
`Rent`.`contract_id` = `Contract`.`id`
AND DATE_FORMAT( `Rent`.`month` , '%Y-%m' ) <> DATE_FORMAT( NOW( ) , '%Y-%m' )
)
This way is more readable and maintainable to me.