繁体   English   中英

MySQL加入+子查询混淆

[英]MySQL joins + sub-query confusion

我需要问一些关于连接真的令人困惑的事情

我的想法,我相信这曾经在过去对我有用,但似乎错过了一些东西:

此查询将生成两个表中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;

现在,我认为这个查询应该返回相同的结果,因为我已经在连接中使用了子查询来首先过滤结果,即。 从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;

问题:

1)在xA and xB使用大量数据的哪种方法更有效?

2)为什么第二种方法2A给出了client_ids other then 1结果,尽管在连接中单独运行子查询可以正常工作

3)如果不使用where子句, 2B的子查询是否会对来自父级的每条记录执行?

4)如果我将1A查询更改为,该怎么办?

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

刚刚删除了客户端表上的where子句,并将其放在子表的join子句中,这是有效的还是where子句?

问候

2a因为您使用了左连接 - 即左侧的所有记录,但只使用了右侧的相关记录,因此拉出了额外的客户端。 你应该使用'完全加入'或'加入',而不是'左连接'。

不确定其他问题,但我的偏好是1B超过次选

编辑添加 - 要了解左连接发生了什么,请考虑其中的一个用途 - 哪些客户端在client_modules中没有任何记录?

写作很诱人:

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

但是,以下内容可能更有效:

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

(即仅显示无法加入client_module行的客户端的记录)

不,他们。 在我看来,我认为你不应该使用left join 你应该使用一个join 像老虎钳一样:

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

这是更加严格的前进,你在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;

使用此查询,您将返回客户端表中的所有行,并且对于那些可以与client_moduless.client_id = clients.client_id匹配的行,您将拥有该表。 但这不是限制JOIN它是一个左连接,这意味着当没有匹配的值时它返回null。 将为每一行运行子查询。 为了获得相同的效果,你可以这样做:

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;

现在这将限制clients表,您将获得client_modules匹配的值。 但我不明白这样做的意义。 我会选择join海峡前锋。

它还取决于您感兴趣的内容。如果您只是在clients表的列中。 然后你可以这样做:

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

因此,如果您希望clients表和client_modules所有列都使用连接。 否则就去exists

编辑

我认为这:

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

和这个:

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

是一样的。 这将导致大多数cretin导致相同的查询计划。

暂无
暂无

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

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