我需要问一些关于连接真正令人困惑的事情
我的想法,我相信这曾经过去曾经为我效劳,但似乎错过了一些东西:
此查询会生成两个表中的数据,其中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子句?
此致
答案 0 :(得分:1)
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行的客户端的记录)
答案 1 :(得分:1)
没有。在我看来,我认为你不应该使用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
是一样的。这将导致相同的查询计划。