简体   繁体   中英

Three Table Join with limit on 2 tables

I've got a bit of a tricky one here, 3 tables as follows in SQLite:

Cars Table

.------.------.--------------.---------.
| vin  | year |     make     |  model  |
'------+------+--------------+---------'
| 1234 | 1965 | Aston Martin | DB5     |
| 5678 | 1965 | Ford         | Mustang |
| 9012 | 1994 | Ford         | Tarus   |
`--------------------------------------'

Price Table

.------.-------.---------------------.
| vin  | price |    last_modified    |
'------+-------+---------------------'
| 1234 | 60000 | 2012-08-01 12:00:00 |
| 1234 | 58000 | 2012-08-02 12:00:00 |
| 1234 | 56000 | 2012-08-10 12:00:00 |
| 5678 | 30000 | 2012-08-02 12:00:00 |
| 9012 |  1000 | 2012-08-01 12:00:00 |
`------------------------------------'

Mileage Table

.------.---------.---------------------.
| vin  | mileage |    last_modified    |
'------+---------+---------------------'
| 1234 |   35000 | 2012-08-01 12:00:00 |
| 1234 |   35030 | 2012-08-02 12:00:00 |
| 1234 |   35100 | 2012-08-10 12:00:00 |
| 5678 |   60000 | 2012-08-02 12:00:00 |
| 9012 |  245000 | 2012-08-01 12:00:00 |
`--------------------------------------'

I'd like to join all three tables to display all the rows from the "Cars" table, but only bring the single most recent "last_modified" price from the price table and the single highest mileage from the mileage table.

At the end my result would look like:

.------.------.--------------.---------.-------.---------.
| vin  | year |     make     |  model  | price | mileage |
'------+------+--------------+---------+-------+---------+
| 1234 | 1965 | Aston Martin | DB5     | 56000 |   35100 |
| 5678 | 1965 | Ford         | Mustang | 30000 |   60000 |
| 9012 | 1994 | Ford         | Tarus   |  1000 |  245000 |
`--------------------------------------------------------'

This is what I would do if I were selecting a specific VIN (ie "1234"):

SELECT
    c.year, c.make, c.model, c.vin, p.price, m.mileage, p.last_modified 
FROM 
    cars c
LEFT JOIN (
            SELECT 
                price, vin, last_modified
            FROM 
                price
            WHERE 
                (vin = '1234')
            ORDER BY
                last_modified DESC LIMIT 1
          ) p
LEFT JOIN (
            SELECT 
                mileage, vin, last_modified 
            FROM 
                mileage 
            WHERE 
                (vin = '1234') 
            ORDER BY 
                mileage DESC LIMIT 1
           ) m

WHERE
    (c.vin = '1234') AND (c.vin = p.vin) AND (c.vin = m.vin)
GROUP BY
    p.vin, m.vin
ORDER BY 
    c.vin, p.last_modified DESC, m.mileage ASC;

...but I'd like to get all the rows from the "Cars" Table.

Anybody have any thoughts?

You need to get their individual maximum modified date in a SubQuery . Try,

SELECT  a.*, b.price, c.mileage
FROM    Cars a
            INNER JOIN Price b
                on a.vin = b.vin
            INNER JOIN Mileage c
                on a.vin = c.vin
            INNER JOIN
            (
                SELECT vin, MAX(last_modified) lastMod
                FROM    Price
                GROUP BY vin
            ) d ON  b.vin = d.vin AND
                    b.last_modified = d.lastMod
            INNER JOIN
            (
                SELECT vin, MAX(last_modified) lastMod
                FROM    Mileage
                GROUP BY vin
            ) e ON  c.vin = e.vin AND
                    c.last_modified = e.lastMod

SQLFiddle Demo

Try this: http://www.sqlfiddle.com/#!5/71705/14

select c.vin, c.year, c.make, c.model, rpci.price, rmci.mileage 
from car c
join 
(  
  select * from mileage m
  join
  (
    select vin, max(last_modified) recent_modified
    from mileage
    group by vin
  ) rm on rm.vin = m.vin and rm.recent_modified = m.last_modified
) rmci on rmci.vin = c.vin
-- rmci: recent mileage complete info ;-)
join
(
  select * from price p
  join
  (
    select vin, max(last_modified) recent_modified
    from price
    group by vin
  ) rp on rp.vin = p.vin and rp.recent_modified = p.last_modified
) rpci on rpci.vin = c.vin
-- rpci: receint price complete info

Output:

| c.vin | c.year |       c.make | c.model | rpci.price | rmci.mileage |
-----------------------------------------------------------------------
|  1234 |   1965 | Aston Martin |     DB5 |      56000 |        35100 |
|  5678 |   1965 |         Ford | Mustang |      30000 |        60000 |
|  9012 |   1994 |         Ford |   Tarus |       1000 |       245000 |

Query progression here: http://www.sqlfiddle.com/#!5/71705/14

You could use correlated queries in the select list. It's ugly, but it would work. http://en.wikipedia.org/wiki/Correlated_subquery

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM