2016-11-27 49 views
2

我不知道添加新列(INFO)如果有一种方法,使从架构中this fiddleuser_idsender_user_idrecipient_user_idname信息。避免多次内部连接到同一表中

我现在能想到的唯一的办法就是做这个嵌套的内部联接,这感觉好像是无效的:

SELECT e.id 
    ,msg_owner 
    ,msg_owner_name 
    ,sender_user_id 
    ,sender_name 
    ,recipient_user_id 
    ,f.NAME AS recipient_name 
    ,msg_body 
    ,created_at 
FROM (
    SELECT c.id 
     ,msg_owner 
     ,msg_owner_name 
     ,sender_user_id 
     ,d.NAME AS sender_name 
     ,recipient_user_id 
     ,msg_body 
     ,created_at 
    FROM (
     SELECT a.id 
      ,user_id AS msg_owner 
      ,NAME AS msg_owner_name 
      ,sender_user_id 
      ,recipient_user_id 
      ,msg_body 
      ,created_at 
     FROM messages AS a 
     INNER JOIN users AS b ON a.user_id = b.id 
     ) AS c 
    INNER JOIN users AS d ON c.sender_user_id = d.id 
    ) AS e 
INNER JOIN users AS f ON e.recipient_user_id = f.id 

有什么(更有效)的方式带来name值每前述三栏?谢谢你的回答/建议!

+1

您的多个内部连接没有任何问题。这是完全正常和正确的。我会做的唯一改变是你不需要三个嵌套选择。 'SELECT a.id,b.id,c.id FROM INNER JOIN b ON aa = bx INNER JOIN c ON ab = cy' work fine ... – MatBailie

+1

你可以发表你想要的结果吗? ,给出样本输入表?由于没有嵌套的聚合组,所以整个事情大部分可能在没有嵌套SELECT的情况下完成,而是使用同一级别的所有连接。 –

+0

@MatBailie谢谢你的建议! – user1330974

回答

1

只是使用联接,而不是嵌套的联接。

你的方法是强制数据库收集每个内部查询的所有结果,然后让它连接到另一个表。除非最内部查询的内容通过WHERE子句非常有限,否则这对性能始终是不利的。

以下是使用连接的正确方法。它允许直接使用索引(如果存在)来加快速度。

SELECT m.id 
    ,owner.id AS msg_owner 
    ,owner.name AS msg_owner_name 
    ,m.sender_user_id 
    ,sender.name AS sender_name 
    ,m.recipient_user_id 
    ,recipient.name AS recipient_name 
    ,m.body AS msg_body 
    ,m.created_at 
FROM messages m 
INNER JOIN users sender 
ON sender.id = m.sender_user_id 
INNER JOIN users recipient 
ON recipient.id = m.recipient_user_id 
INNER JOIN users owner 
ON owner.id = m.user_id 
+0

谢谢你的答案和详细的解释。穆里尼克的回答也是我一直在寻找的,但我会接受你作为“正确”的一个,因为它略有更多的信息。谢谢! – user1330974

+0

@onedaywhen比较每个查询的SQLFiddle中的EXPLAIN计划,可以看到不同之处。但是,您是正确的,它不一定首先查询最里面的行。在我经历过的每一种情况下,当有人创建一个类似于OP的查询时,它的表现比直接连接要糟糕得多。另请参阅https://dev.mysql.com/doc/refman/5.6/en/subquery-optimization.html。稍后我会更新我的答案(工作调用),详细说明OP解释计划中的ref和ALL是如何意味着性能比查询解释计划中的eq_ref更差。 –

1

您可以在同一查询中有多个join子句,而无需嵌套。我不知道,随便,这是否会提高性能或没有,但起码它将使查询不太麻烦:

SELECT m.id, 
     m.user_id AS msg_owner, 
     o.name AS msg_owner_name, 
     m.sender_user_id, 
     s.name, 
     m.recipient_user_id, 
     r.name AS recipient_name, 
     m.body, 
     m.created_at 
FROM messages m 
JOIN users o ON m.user_id = o.id 
JOIN users s ON m.sender_user_id = s.id 
JOIN users r ON m.recipient_user_id = r.id 
+0

以秒为单位打败我。 –

+0

@Mureinik谢谢你回答我的问题!我现在知道可以像这样使用许多'INNER JOIN'。我接受了Willem的回答,因为他解释了一些关于性能的内容,并认为它可能对像我这样的其他SQL初学者有用。 :) – user1330974