简体   繁体   English

MySQL加入+子查询混淆

[英]MySQL joins + sub-query confusion

I need to ask something that really confusing regarding joins 我需要问一些关于连接真的令人困惑的事情

What I think and I am sure this used to work for me in past but seems like am missing some thing: 我的想法,我相信这曾经在过去对我有用,但似乎错过了一些东西:

This query results in data from both tables where client_id is 1 - Working fine 此查询将生成两个表中client_id为1的数据 - 工作正常

/* gets data for one client_id*/

approach 1A

SELECT * 
FROM clients  LEFT JOIN client_modules 
                ON client_modules.client_id = clients.client_id
WHERE clients.client_id = 1;

Now, this query as what I think should return the same result because, I have used the sub-query in the join to filter the result first ie. 现在,我认为这个查询应该返回相同的结果,因为我已经在连接中使用了子查询来首先过滤结果,即。 get data from modules for client_id 1 already but, for some reason its giving other client_ids data in final result. 从client_id 1的模块获取数据,但由于某种原因,它在最终结果中给出了其他client_ids数据。

/* gets data for one client_id sub-query approach*/

approach 2A

SELECT * 
FROM clients LEFT JOIN (SELECT client_id, module_name 
                        FROM client_modules 
                        WHERE client_modules.client_id = 1) 
             AS client_moduless ON client_moduless.client_id = clients.client_id;



/* gets data for all client_ids */

approach 1B

SELECT * FROM clients
LEFT JOIN client_modules ON client_modules.client_id = clients.client_id;



/* gets data for all client_ids*/

approach 2B

SELECT * 
FROM clients LEFT JOIN (SELECT client_id, module_name 
                        FROM client_modules) AS client_moduless
              ON client_moduless.client_id = clients.client_id;

Questions: 问题:

1) Which approach is more efficient to use with large amount of data among xA and xB ? 1)在xA and xB使用大量数据的哪种方法更有效?

2) Why is the second approach 2A giving results from client_ids other then 1 , although running the sub-query in join separately works fine 2)为什么第二种方法2A给出了client_ids other then 1结果,尽管在连接中单独运行子查询可以正常工作

3) Will the sub-query in 2B execute for every record from parent if not using where clause? 3)如果不使用where子句, 2B的子查询是否会对来自父级的每条记录执行?

4) what if I change the 1A query to 4)如果我将1A查询更改为,该怎么办?

SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id AND client_modules.client_id = 1

have just removed the where clause on client table and putted that in the join clause on child table is this efficient or the where clause? 刚刚删除了客户端表上的where子句,并将其放在子表的join子句中,这是有效的还是where子句?

Regards 问候

2a pulls extra clients because you've used a left join - ie all records from the left side, but only related records from the right side. 2a因为您使用了左连接 - 即左侧的所有记录,但只使用了右侧的相关记录,因此拉出了额外的客户端。 You should use 'full join' or 'join', not 'left join'. 你应该使用'完全加入'或'加入',而不是'左连接'。

Not sure about the other questions, but my preference would be for 1B over sub-selects 不确定其他问题,但我的偏好是1B超过次选

Edit to add - to understand what's happening with a left join, consider one of its many uses - which clients don't have any records in client_modules? 编辑添加 - 要了解左连接发生了什么,请考虑其中的一个用途 - 哪些客户端在client_modules中没有任何记录?

It's tempting to write: 写作很诱人:

SELECT * FROM clients WHERE clientid NOT IN (select distinct(clientid) FROM client_modules)

However, the following is probably more efficient to write: 但是,以下内容可能更有效:

SELECT * FROM clients
     LEFT JOIN  client_modules ON clients.clientid = client_modules.clientid
WHERE client_modules.clientid IS NULL

(ie only show the records from clients that can't be joined to a client_module row) (即仅显示无法加入client_module行的客户端的记录)

No of them. 不,他们。 In my mind i think you should not be using a left join . 在我看来,我认为你不应该使用left join You should use a join . 你应该使用一个join Like vise: 像老虎钳一样:

SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id
WHERE clients.client_id = 1;

That is more strait forward and you are limiting the LEFT JOIN in the where statement so it has the same effect. 这是更加严格的前进,你在where语句中限制LEFT JOIN ,因此它具有相同的效果。

SELECT * 
FROM clients LEFT JOIN (SELECT client_id, module_name 
                        FROM client_modules 
                        WHERE client_modules.client_id = 1) 
             AS client_moduless ON client_moduless.client_id = clients.client_id;

With this query you will return all the rows in the client table and for those that it can match the client_moduless.client_id = clients.client_id you will have a that table. 使用此查询,您将返回客户端表中的所有行,并且对于那些可以与client_moduless.client_id = clients.client_id匹配的行,您将拥有该表。 But this is not a limiting JOIN it is a left join so that means that when no values is matched it return null. 但这不是限制JOIN它是一个左连接,这意味着当没有匹配的值时它返回null。 The subquery will be run for every row. 将为每一行运行子查询。 To get the same effect you can do it like this: 为了获得相同的效果,你可以这样做:

SELECT * 
FROM clients JOIN (SELECT client_id, module_name 
                        FROM client_modules 
                        WHERE client_modules.client_id = 1) 
             AS client_moduless ON client_moduless.client_id = clients.client_id;

Now this will limit the clients table and you will just get the values that has a match in client_modules . 现在这将限制clients表,您将获得client_modules匹配的值。 But I cannot see a point of doing that. 但我不明白这样做的意义。 I would go with the strait forward join instead. 我会选择join海峡前锋。

It also depend on what you are interested in. If you are just in the columns from the clients table. 它还取决于您感兴趣的内容。如果您只是在clients表的列中。 Then you can do this: 然后你可以这样做:

SELECT * 
FROM clients
WHERE EXISTS
(
    SELECT 
        NULL
    FROM
        client_modules=1
        AND client_moduless.client_id = clients.client_id
)

So if you want all the columns from the clients table and the client_modules go with the join. 因此,如果您希望clients表和client_modules所有列都使用连接。 Otherwise go with the exists 否则就去exists

EDIT 编辑

I think this: 我认为这:

SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id 
AND client_modules.client_id = 1

And this: 和这个:

SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id
WHERE client_modules.client_id = 1

is the same. 是一样的。 This will most cretin result in the same query plan. 这将导致大多数cretin导致相同的查询计划。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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