【问题标题】:Three Table Join with limit on 2 tables三表连接,限制为 2 个表
【发布时间】:2012-08-21 03:35:30
【问题描述】:

我这里有点棘手,SQLite 中的 3 个表如下:

汽车表

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

价格表

.------.-------.---------------------.
| 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 |
`------------------------------------'

里程表

.------.---------.---------------------.
| 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 |
`--------------------------------------'

我想连接所有三个表以显示“汽车”表中的所有行,但只带来价格表中的单个最新“last_modified”价格和里程表中的单个最高里程。

最后我的结果是这样的:

.------.------.--------------.---------.-------.---------.
| 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 |
`--------------------------------------------------------'

如果我选择特定的 VIN(即“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;

...但我想从“汽车”表中获取所有行。

有人有什么想法吗?

【问题讨论】:

    标签: sql sqlite join


    【解决方案1】:

    您需要在SubQuery 中获取他们各自的最大修改日期。试试吧,

    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

    【讨论】:

    • 这在大多数情况下都有效,最后一个子查询的一个小修正:INNER JOIN (SELECT vin, MAX(mileage) maxMileage FROM Mileage GROUP BY vin) e ON c.vin = e.vin AND c.mileage = e.maxMileage
    • @JohnWoo Kabayan!ツ 查询SELECT a.*, b.price, c.mileage FROM Car a INNER JOIN Price b on a.vin = b.vin INNER JOIN Mileage c on a.vin = c.vin 的第一部分产生笛卡尔的行。例如:Ashton Martin 有 3 个价格和 3 个里程行,链式连接产生笛卡尔(这里是 9)行。我手头没有大数据,但我预感到这不会很好地扩展。以后测试的时候会给你反馈ツ
    • @MichaelBuen 感谢您在 sqlfiddle 的 DDL。它起作用了 kabayan,因为即使它在第一次连接时给出了笛卡尔积,然后在连接的最后部分被过滤了 c.vin = e.vin AND c.last_modified = e.lastMod1b.vin = d.vin AND b.last_modified = d.lastMod
    • 是的,我知道它可以工作 kabayan,我的意思是中间行(前两个连接的结果,它产生笛卡尔行,根据两个表的笛卡尔积可能会变大)后续加入,可能会对性能产生影响ツ
    • 我明白你的意思@MichaelBuen :),我会更新它 kabayan。让我为此找到另一种选择..
    【解决方案2】:

    试试这个: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
    

    输出:

    | 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 |
    

    此处查询进度:http://www.sqlfiddle.com/#!5/71705/14

    【讨论】:

      【解决方案3】:

      您可以在选择列表中使用相关查询。这很丑陋,但它会起作用。 http://en.wikipedia.org/wiki/Correlated_subquery

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-07
        • 1970-01-01
        • 2018-05-22
        • 2016-12-20
        • 1970-01-01
        • 2018-11-06
        • 2014-02-24
        • 1970-01-01
        相关资源
        最近更新 更多