首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL联接+子查询混淆

问MySQL联接+子查询混淆
EN

Stack Overflow用户
提问于 2012-05-16 08:51:15
回答 2查看 121关注 0票数 0

我想问一些关于联接的问题

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

此查询将生成来自两个表的数据,其中client_id为1-工作正常。

代码语言:javascript
复制
/* 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数据。

代码语言:javascript
复制
/* 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的结果,尽管在join中分别运行子查询很好。

3)如果不使用where子句,2B中的子查询会对父记录执行吗?

4)如果我将1A查询更改为

代码语言:javascript
复制
SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id AND client_modules.client_id = 1

刚刚删除了client表上的where子句,并在子表的join子句中添加了这是有效的还是where子句?

问候

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-05-16 09:01:38

不是他们中的。在我看来,我认为您不应该使用left join。您应该使用join。像老虎钳:

代码语言:javascript
复制
SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id
WHERE clients.client_id = 1;

这是更严格的前进,你限制在where语句中的LEFT JOIN,所以它有同样的效果。

代码语言:javascript
复制
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匹配的行,将有一个该表。但是这不是一个限制联接,而是一个左连接,这意味着当没有匹配值时,它返回null。子查询将针对每一行运行。为了达到同样的效果,你可以这样做:

代码语言:javascript
复制
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。

这也取决于你对什么感兴趣。如果您只是在客户端表的列中。然后你就可以这样做:

代码语言:javascript
复制
SELECT * 
FROM clients
WHERE EXISTS
(
    SELECT 
        NULL
    FROM
        client_modules=1
        AND client_moduless.client_id = clients.client_id
)

因此,如果您希望clients表和client_modules中的所有列都与联接一起使用。否则,请与exists一起使用

编辑

我想这个:

代码语言:javascript
复制
SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id 
AND client_modules.client_id = 1

这是:

代码语言:javascript
复制
SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id
WHERE client_modules.client_id = 1

是一样的。这将导致相同的查询计划。

票数 1
EN

Stack Overflow用户

发布于 2012-05-16 09:01:24

2a吸引额外的客户端,因为您已经使用了一个左连接-即所有记录从左侧,但只有相关的记录从右侧。你应该使用“完全连接”或“加入”,而不是“左加入”。

不确定其他的问题,但我更喜欢1B而不是分选。

编辑以添加-要了解左联接发生了什么,考虑它的许多用途之一-客户端在client_modules中没有任何记录?

这是很容易写的:

代码语言:javascript
复制
SELECT * FROM clients WHERE clientid NOT IN (select distinct(clientid) FROM client_modules)

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

代码语言:javascript
复制
SELECT * FROM clients
     LEFT JOIN  client_modules ON clients.clientid = client_modules.clientid
WHERE client_modules.clientid IS NULL

(即仅显示来自客户端的无法连接到client_module行的记录)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10615054

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档