0

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

我的想法,我确信这过去对我有用,但似乎缺少一些东西:

此查询导致来自两个表的数据,其中 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,尽管在 join 中单独运行子查询可以正常工作

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 子句?

问候

4

2 回答 2

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 行的客户端的记录)

于 2012-05-16T09:01:24.973 回答
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在 where 语句中限制了它,因此它具有相同的效果。

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

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

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

因此,如果您想要表中的所有列clientsclient_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 导致相同的查询计划。

于 2012-05-16T09:01:38.360 回答