我有两个表,Clients
和Contacts
(见下文),并希望获取所有客户端,只有最后添加的联系人。
我几乎在考虑使用子查询,因为我无法在我加入的联系人上使用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
答案 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)