这个(工作)查询背后的解释?

时间:2013-06-19 19:17:02

标签: mysql sql

我有两个表,ClientsContacts(见下文),并希望获取所有客户端,只有最后添加的联系人。

我几乎在考虑使用子查询,因为我无法在我加入的联系人上使用LIMIT 1,直到我偶然发现这个解决方案,这似乎非常简单。

问题是,我真的不明白它在做什么。 WHERE条款背后的逻辑也超出了我的范围。

对此提出的问题:两个连接是否仍然比子查询更快?

PS:我正在使用MySQL。

感谢。

SELECT
    cl.clientId as clientId,
    cl.clientName as clientName,
    c1.firstName as firstName,
    c1.lastName as lastName,
    c1.added as added
FROM Clients as cl
LEFT JOIN Contacts as c1 ON cl.clientId = c1.clientId
LEFT JOIN Contacts as c2 ON cl.clientId = c2.clientId AND c1.added < c2.added
WHERE c2.added IS NULL

客户

-----------------------------
 clientId     clientName
-----------------------------
    1          Johnny's
    2          Bonnie's

联系人

-------------------------------------------------------
 clientId     firstName     lastName        added
-------------------------------------------------------
    1          Johnny        Simmons      2013-06-17
    1          Jane          Simmons      2013-06-18
    2          Bonnie        Hall         2013-06-19

结果

----------------------------------------------------------------------
 clientId     clientName     firstName     lastName        added
----------------------------------------------------------------------
    1          Johnny's       Jane          Simmons      2013-06-18
    2          Bonnie's       Bonnie        Hall         2013-06-19

2 个答案:

答案 0 :(得分:4)

LEFT JOIN Contacts as c2 ON cl.clientId = c2.clientId AND c1.added < c2.added
WHERE c2.added IS NULL

where子句说:Contacts中与cl.clientId = c2.clientId AND c1.added < c2.added匹配的行不能。{1}}。这会过滤掉之前添加的其他联系人的所有联系人。

因此,您最终会得到每位客户的最新联系。

答案 1 :(得分:1)

LEFT JOIN ... WHERE NULL等同于此NOT EXISTS()查询。平台之间的性能可能不同(人们会期望两个版本的查询计划相同) Mysql人似乎更喜欢max(added)子查询。

SELECT
    cl.clientId as clientId,
    cl.clientName as clientName,
    c1.firstName as firstName,
    c1.lastName as lastName,
    c1.added as added
FROM Clients as cl
LEFT JOIN Contacts as c1 ON cl.clientId = c1.clientId
WHERE NOT EXISTS (
  SELECT 1 FROM Contacts as c2 
  WHERE cl.clientId = c2.clientId
    AND c1.added < c2.added
  );

解释与@Andomar的回答相同,如果c1.added是最大值(对于此client_id),则不存在具有更高值的另一条记录(对于此client_id)

相关问题