按ContactPrimaryNum分组,筛选最新日期的SQL实现方案问询
解决思路与SQL实现
优先方案:用窗口函数精准筛选(高效简洁)
窗口函数能直接按分组排序,同时保留所有联系人条目,包括那些没有笔记、或Contact_Follow_Up_Date为NULL的记录:
WITH ranked_notes AS ( SELECT c.Contact_Primary_Num, cn.Contact_Note_Date, cn.Contact_Follow_Up_Date, -- 先按笔记日期降序排,同日期下再按跟进日期降序排 ROW_NUMBER() OVER ( PARTITION BY c.Contact_Primary_Num ORDER BY cn.Contact_Note_Date DESC NULLS LAST, cn.Contact_Follow_Up_Date DESC NULLS LAST ) AS rn FROM contacts c LEFT JOIN contact_notes cn ON c.Contact_Primary_Num = cn.Contact_Primary_Num ) SELECT Contact_Primary_Num, Contact_Note_Date, Contact_Follow_Up_Date FROM ranked_notes WHERE rn = 1;
NULLS LAST是让NULL值排在有效日期之后,保证最新的非NULL日期优先;如果你的数据库不支持这个语法(比如MySQL 8.0之前),可以改成ORDER BY ISNULL(cn.Contact_Note_Date), cn.Contact_Note_Date DESC来实现同样效果。LEFT JOIN保证所有联系人都被保留,不会因为没有对应笔记而被过滤。
兼容方案:子查询+UNION ALL(适配老版本数据库)
如果你的数据库不支持窗口函数,用子查询先抓每组的最新日期,再通过UNION ALL补充无笔记的联系人条目:
SELECT c.Contact_Primary_Num, cn.Contact_Note_Date, cn.Contact_Follow_Up_Date FROM contacts c LEFT JOIN contact_notes cn ON c.Contact_Primary_Num = cn.Contact_Primary_Num WHERE (cn.Contact_Primary_Num, cn.Contact_Note_Date, cn.Contact_Follow_Up_Date) IN ( SELECT Contact_Primary_Num, MAX(Contact_Note_Date) AS max_note_date, MAX(Contact_Follow_Up_Date) AS max_follow_date FROM contact_notes GROUP BY Contact_Primary_Num UNION ALL -- 补上没有对应笔记的联系人,避免遗漏NULL条目 SELECT Contact_Primary_Num, NULL, NULL FROM contacts WHERE Contact_Primary_Num NOT IN (SELECT DISTINCT Contact_Primary_Num FROM contact_notes) );
核心要点
- 必须用
LEFT JOIN关联两张表,确保所有原始联系人都被包含 - 处理NULL值时要注意排序规则,避免NULL被错误地当成“最新”值过滤掉
- 窗口函数方案性能更优,代码可读性也更强,优先选用
内容的提问来源于stack exchange,提问作者Progolfer79
相关产品推荐
相关产品推荐

