SQL多表关联问题:获取客户最新创建地址的TOP1关联实现
我来帮你搞定这个查询问题!你遇到的关联困扰大概率是没处理好「一个客户对应多个地址」的场景——毕竟要筛选出最新创建的那条地址,得先给每个客户的地址做个排序筛选,再和主表关联才行。
下面给你两种常用的解决方案,都是针对你的表结构设计的:
方案1:用窗口函数(推荐,逻辑清晰易维护)
窗口函数可以轻松给每个客户的地址按创建时间排序,直接取最新的那条:
WITH CustomerLatestLocations AS ( SELECT cl.CustomerID, l.LocationID, l.StreetAddress1, l.StreetAddress2, l.City, l.State, l.Zip, l.Country, l.CreatedDate, -- 按客户分组,地址按创建时间倒序排,最新的地址标记为1 ROW_NUMBER() OVER (PARTITION BY cl.CustomerID ORDER BY l.CreatedDate DESC) AS rn FROM CustomerLocations cl JOIN Locations l ON cl.LocationID = l.LocationID ) SELECT c.CustomerID, CONCAT(c.FirstName, ' ', c.LastName) AS CustomerName, cll.StreetAddress1, cll.StreetAddress2, cll.City, cll.State, cll.Zip, cll.Country, cll.CreatedDate AS LatestAddressCreatedDate FROM Customers c -- 用LEFT JOIN保留没有地址的客户,不需要的话换成INNER JOIN LEFT JOIN CustomerLatestLocations cll ON c.CustomerID = cll.CustomerID AND cll.rn = 1 ORDER BY c.CustomerID;
逻辑说明:
- 先通过CTE(临时结果集)关联
CustomerLocations和Locations,给每个客户的地址按CreatedDate倒序编号; - 主查询里只取编号为1的地址(也就是最新的那条),和
Customers表关联得到最终结果。
方案2:用子查询筛选最新地址
如果你的数据库不支持窗口函数(比如老版本MySQL),可以用子查询先找到每个客户的最新地址创建时间,再关联回去:
SELECT c.CustomerID, CONCAT(c.FirstName, ' ', c.LastName) AS CustomerName, l.StreetAddress1, l.StreetAddress2, l.City, l.State, l.Zip, l.Country, l.CreatedDate AS LatestAddressCreatedDate FROM Customers c LEFT JOIN ( SELECT cl.CustomerID, l.* FROM CustomerLocations cl JOIN Locations l ON cl.LocationID = l.LocationID WHERE (cl.CustomerID, l.CreatedDate) IN ( -- 先找出每个客户的最新地址创建时间 SELECT cl_inner.CustomerID, MAX(l_inner.CreatedDate) FROM CustomerLocations cl_inner JOIN Locations l_inner ON cl_inner.LocationID = l_inner.LocationID GROUP BY cl_inner.CustomerID ) ) l ON c.CustomerID = l.CustomerID ORDER BY c.CustomerID;
注意:
如果一个客户在同一时间创建了多个地址,这个方案会返回多条记录;而方案1的窗口函数可以通过调整排序条件(比如加上l.LocationID DESC)来确保只返回一条。
内容的提问来源于stack exchange,提问作者mydisplay
相关产品推荐
相关产品推荐

