在mysql查询中连接两次相同的表

时间:2013-11-14 01:08:28

标签: mysql sql

我试图了解此查询中联接的目的是什么。

SELECT 
    DISTINCT o.order_id 
FROM 
    `order` o, 
    `order_product` as op 
LEFT JOIN `provider_order_product_status_history` as popsh 
    on op.order_product_id = popsh.order_product_id 
LEFT JOIN  `provider_order_product_status_history` as popsh2 
    ON popsh.order_product_id = popsh2.order_product_id 
        AND popsh.provider_order_product_status_history_id < 
               popsh2.provider_order_product_status_history_id 
WHERE 
    o.order_id = op.order_id 
    AND popsh2.last_updated IS NULL 
LIMIT 10

困扰我的是,provider_order_product_status_history已加入2次,我不确定它的用途。非常感谢有人可以提供帮助

3 个答案:

答案 0 :(得分:2)

这是一种检索最新订单状态的技术。

因为

AND popsh.provider_order_product_status_history_id < popsh2.provider_order_product_status_history_id

AND popsh2.last_updated IS NULL

仅返回没有任何新状态的订单状态。

对于最小设置示例,请考虑以下状态历史记录表:

id  status order_id last_updated
--------------------------------
1   A      X        1:00
2   B      X        2:00

自我加入将导致:

id  status order_id last_updated    id  status order_id last_updated
--------------------------------    --------------------------------
1   A      X        1:00            2   B      X        2:00
2   B      X        2:00                NULL   NULL     NULL

第一行将被IS NULL条件过滤掉,只留下第二行,即最新的一行。

对于3行案例,自联接结果将为:

id  status order_id last_updated    id  status order_id last_updated
--------------------------------    --------------------------------
1   A      X        1:00            2   B      X        2:00
1   A      X        1:00            3   C      X        3:00
2   B      X        2:00            3   C      X        3:00
3   C      X        3:00                NULL   NULL     NULL

只有最后一个会通过IS NULL条件,再次留下最新版本。

看起来这是一种不必要的复杂工作方式,但实际上它非常有效,因为RDBMS引擎可以非常有效地加入。

顺便说一下,由于查询只检索order_id,因此查询无效。我猜OP省略了select子句中的其他字段。它应该类似于SELECT o.order_id, popsh.* FROM ...

答案 1 :(得分:0)

等等,你有一个错误:

SELECT 
    DISTINCT o.order_id 
FROM 
    `order` o, 
    `order_product` as op 
LEFT JOIN `provider_order_product_status_history` as popsh 
    on op.order_product_id = popshs.order_product_id 
  ** YOU HAVE EXCESS 's' HERE     ^
LEFT JOIN  `provider_order_product_status_history` as popsh2 
    ON popsh.order_product_id = popsh2.order_product_id 
        AND popsh.provider_order_product_status_history_id < popsh2.provider_order_product_status_history_id 
WHERE 
    o.order_id = op.order_id 
    AND popsh2.last_updated IS NULL 
LIMIT 10

根据我的分析,查询是尝试来提取{{1>的第一个o.order_id或第一个条目(基于provider_order_product_status_history.provider_order_product_status_history_id) }}。但是,此查询中使用的连接语义不可重复使用。

答案 2 :(得分:0)

两个连接都是条件上的内部限制结果集。它就像“gimme只有来自表1的值在条件1的表2中具有相应的行,同时在条件2的表2中具有一行”。