Domanda

My tables structure is as follows:

units {id, owner_id}
contracts {id, rent, unit_id}
rents {paid, contract_id}

What i need, is the sum of two things: all rents.paid and the sum of contracts.rent.

My query is:

SELECT 
   Sum(Rent.paid)      AS Rent__summed_rents
FROM
   rents AS Rent
LEFT JOIN contracts
   ON contracts.id = Rent.id
LEFT JOIN units
   ON contracts.unit_id = units.id AND units.owner_id = 29

I tried to add contracts.rent * Rent.paid AS Rent__summed_expected_rents, but it didn't work.


edit

Each contract has a column rent, which contains the payment expected for each month.
Each rent record has a column paid which contains the actual payment made.
The query should get all the paid records and sum them (summed_rents), it also should tell me what was the expected income (which is contracts.rent * rents.paid)

* edit #2 *

rents data:
id | paid | contract_id
 1 | 200  |      6
 1 | 300  |      6
 1 | 500  |      4
 1 | 200  |      4

contracts data:
id | rent |  unit_id
 6 | 500  |    22
 4 | 600  |    22

units data:
id | owner_id
22 |    29

What i expect is: summed rents = 1,200 (sum of all paid) expected rents = 2,200 = (500 * 2) + (600 *2) (sum of contract.rent, one for each rents record)

È stato utile?

Soluzione

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

Altri suggerimenti

It's as easy as:

select sum(r.paid) as rent_paid,
       sum(c.rent) as expected_rent
  from rents r
  join contracts c on (r.contract_id = c.id)
  join units u on (c.unit_id = u.id)
 where u.owner_id = 29;

As seen on sqlfiddle

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top