2012-05-16 136 views
0

我需要问一些真正令人困惑关于加入MySQL的加入+子查询混乱

我想什么,我相信这为我所用过去的工作,但好像是缺少了一些东西:

此查询结果在两个表中,其中的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)为什么是第二个方法2Aclient_ids other then 1给出的结果,尽管运行子查询中分别加入正常工作

3)将在2B子查询,如果不使用执行从父每个记录where子句?

4)如果我改变1A查询

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

刚刚取消了对客户表中的WHERE子句和推杆上的子表联接子句中是这种高效或where子句?即从左侧的所有记录,但只能从右侧相关的记录 - 因为你已经使用了左连接

问候

回答

1

没有。在我看来,我认为你不应该使用left join。你应该使用join。像老虎钳:

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

这是两岸更向前,你是在哪里声明限制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表中的列和client_modules去的加入让

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

:然后你就可以做到这一点。否则,用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 

是一样的。这将使绝大多数的克莱汀产生相同的查询计划。

+0

用于识别'LEFT JOIN'我知道这一点,但这是我错过了:),但是子查询与直接连接表名有什么关系?任何想法? – Junaid

+0

更新了答案 – Arion

+0

赞赏!请参阅更新后的问题 – Junaid

1

2A拉额外的客户端。你应该使用'全连接'或'连接',而不是'左连接'。

不知道的其他问题,但我更倾向于将用于1B在子选择

编辑补充 - 了解什么用左发生的加入,考虑它的许多用途之一 - 其客户不要” t在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 row)

+0

用于识别'LEFT JOIN'我知道这一点,但这是我想念的东西:),请你让我知道不使用子选择背后的原因是什么? – Junaid

+0

TBH'个人偏好' - 我的直觉是在这种情况下的子查询是没有必要的,并且可能会更难以优化sql ...那说,我有时会发现一种最适合于一个数据集的方法可能效率较低和另外一个。问题是'速度够快吗?' (又名避免过早优化)如果不是,尝试其他方法(可能包括添加其他索引),直到您获得合理的性能。 –