在mysql查询中连接同一个表两次

在mysql查询中连接同一个表两次,mysql,sql,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_s

我试图理解这个查询中连接的目的是什么

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
选择
不同的订单号
从…起
`命令`o,
`订购“产品”作为op
左键作为popsh连接“提供者\订单\产品\状态\历史”
在op.order\u product\u id=popsh.order\u product\u id上
以popsh2的形式左键加入“供应商\订单\产品\状态\历史记录”
在popsh.order\u product\u id=popsh2.order\u product\u id上
和popsh.provider\u order\u product\u status\u history\u id<
popsh2.provider\u order\u product\u status\u history\u id
哪里
o、 订单号=操作订单号
而popsh2.last_updated为空
限制10

让我烦恼的是,供应商、订单、产品、状态、历史记录已经加入了2次,我不确定它的目的。非常感谢有人能帮助您等待,您有一个错误:

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
选择
不同的订单号
从…起
`命令`o,
`订购“产品”作为op
左键作为popsh连接“提供者\订单\产品\状态\历史”
在op.order\u product\u id=popshs.order\u product\u id上
**这里有多余的“s”^
以popsh2的形式左键加入“供应商\订单\产品\状态\历史记录”
在popsh.order\u product\u id=popsh2.order\u product\u id上
和popsh.provider\u order\u product\u status\u history\u id

根据我的分析,查询试图提取
提供商订单产品状态历史记录的第一个o.order\u id或第一个条目(基于
提供商订单产品状态历史记录。提供商订单产品状态历史记录
)。但是,不建议使用此查询中使用的联接语义。

两个联接都是内部种类限制条件上的结果集。这就像“只给表1中的值赋值,这些值在条件1的表2中有对应的行,同时在条件2的表2中有对应的行。”

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

因为

AND popsh.provider_order_product_status_history_id < popsh2.provider_order_product_status_history_id
只返回那些没有任何更新状态的订单状态

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

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
第一行将被
为NULL
条件过滤掉,只留下第二行原始数据,这是最新的一行

对于三行情况,自联接结果将为:

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\u id,popsh.*FROM…

感谢您指出错误并回答,我更新了问题。回答得很好!。谢谢你解释这个技巧。是的,我只放了查询的重要部分。
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