You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于MIN/MAX(Date)查询客户注册首尾日期对应渠道类型的SQL问题

解决方法:获取每个客户首次/末次注册尝试的渠道类型

你当前的查询已经成功拿到了每个客户的最早和最晚尝试日期,但确实没关联到对应的渠道信息。下面提供两种常用的解决方案,适用于大多数主流SQL数据库(比如MySQL、PostgreSQL、SQL Server等):

方法1:使用窗口函数(推荐,简洁高效)

窗口函数可以帮我们给每个客户的注册尝试记录按日期排序,精准标记出最早和最晚的那条记录,之后再提取对应的渠道信息。

步骤说明:

  • 用ROW_NUMBER()窗口函数,按CustomerID分组,分别按DateAttempt升序(标记最早尝试)和降序(标记最晚尝试)排序,给每条记录分配序号。
  • 筛选出序号为1的记录(也就是每个客户最早和最晚的尝试记录)。
  • 最后用条件聚合把同一个客户的两个渠道信息合并到一行结果中。

示例代码:

WITH RankedAttempts AS (
    SELECT
        CustomerID,
        DateAttempt,
        Channel,
        -- 标记最早尝试的记录
        ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY DateAttempt ASC) AS rn_earliest,
        -- 标记最晚尝试的记录
        ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY DateAttempt DESC) AS rn_latest
    FROM EnrollmentAttempt
)
SELECT
    CustomerID,
    -- 获取最早尝试的渠道
    MAX(CASE WHEN rn_earliest = 1 THEN Channel END) AS EarliestChannel,
    MAX(CASE WHEN rn_earliest = 1 THEN DateAttempt END) AS EarliestAttempt,
    -- 获取最晚尝试的渠道
    MAX(CASE WHEN rn_latest = 1 THEN Channel END) AS MostRecentChannel,
    MAX(CASE WHEN rn_latest = 1 THEN DateAttempt END) AS MostRecentAttempt
FROM RankedAttempts
WHERE rn_earliest = 1 OR rn_latest = 1
GROUP BY CustomerID;

小提示:如果同一个客户在最早/最晚日期有多个渠道尝试(比如同一天同时用MAIL和WEB提交了注册),ROW_NUMBER()会随机选取一条记录。如果想保留所有渠道,可以把ROW_NUMBER()换成RANK(),并把MAX()换成GROUP_CONCAT(Channel SEPARATOR ', ')(MySQL)或者STRING_AGG(Channel, ', ')(PostgreSQL/SQL Server)来合并多个渠道值。

方法2:子查询关联(兼容旧版SQL)

如果你的数据库不支持窗口函数(比如非常老旧的MySQL版本),可以用子查询先拿到每个客户的最早/最晚日期,再关联原表获取对应渠道:

示例代码:

SELECT
    main.CustomerID,
    earliest.Channel AS EarliestChannel,
    main.EarliestAttempt,
    latest.Channel AS MostRecentChannel,
    main.MostRecentAttempt
FROM (
    -- 先拿到每个客户的最早和最晚日期
    SELECT
        CustomerID,
        MIN(DateAttempt) AS EarliestAttempt,
        MAX(DateAttempt) AS MostRecentAttempt
    FROM EnrollmentAttempt
    GROUP BY CustomerID
) main
-- 关联原表获取最早日期对应的渠道
LEFT JOIN EnrollmentAttempt earliest
    ON main.CustomerID = earliest.CustomerID
    AND main.EarliestAttempt = earliest.DateAttempt
-- 关联原表获取最晚日期对应的渠道
LEFT JOIN EnrollmentAttempt latest
    ON main.CustomerID = latest.CustomerID
    AND main.MostRecentAttempt = latest.DateAttempt
GROUP BY main.CustomerID, main.EarliestAttempt, main.MostRecentAttempt;

小提示:如果同一日期存在多个渠道记录,这个查询会返回多行结果。此时可以用聚合函数(比如MAX(earliest.Channel))来合并渠道值,或者根据业务需求选择其中一个渠道即可。


内容的提问来源于stack exchange,提问作者kaysuez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:38:22