Here's how I'd build the query:
start with units for an owner. simple enough:
SELECT u.*
FROM units u
WHERE u.owner_id = 29
next step, get the contracts on those units:
SELECT c.*
, u.*
FROM units u
JOIN contracts c
ON c.unit_id = u.id
WHERE u.owner_id = 29
next step, get the rents paid on those contracts
SELECT r.*
, c.*
, u.*
FROM units u
JOIN contracts c
ON c.unit_id = u.id
JOIN rents r
ON r.contract_id = c.id
WHERE u.owner_id = 29
-- aggregate the rows from that result by contracts id (per the specification, we need the count from rents by contract number, to multiply by the contracts rent amount)
SELECT SUM(r.paid) AS total_paid
, SUM(c.rent) AS total_rent
FROM units u
JOIN contracts c
ON c.unit_id = u.id
JOIN rents r
ON r.contract_id = c.id
WHERE u.owner_id = 29
GROUP BY c.id
-- get grand totals by wrapping that result as an inline view, and aggregating the total_paid and total rent
SELECT SUM(t.total_paid) AS total_paid
, SUM(t.total_rent) AS total_rent
FROM (
SELECT SUM(r.paid) AS total_paid
, SUM(c.rent) AS total_rent
FROM units u
JOIN contracts c
ON c.unit_id = u.id
JOIN rents r
ON r.contract_id = c.id
WHERE u.owner_id = 29
GROUP BY c.id
) t
NOTE: counting the number of rows in rents
for a given contract seems an odd way to get the multiplier for rent. But if that's the specification, we make sure our code does that.
We'd only need outer joins to generate "zero" paid and "zero" rent. If we introduce a LEFT JOIN to the rents table, then we'd need to adjust the expression to get total_rent. We'd want to use something like:
c.rent*COUNT(r.contract_id) AS total_rent
Something like this:
SELECT IFNULL(SUM(t.total_paid),0) AS total_paid
, IFNULL(SUM(t.total_rent),0) AS total_rent
FROM (
SELECT SUM(r.paid) AS total_paid
, c.rent*COUNT(r.contract_id) AS total_rent
FROM units u
JOIN contracts c
ON c.unit_id = u.id
LEFT
JOIN rents r
ON r.contract_id = c.id
WHERE u.owner_id = 29
GROUP BY c.id
) t