首页 > 试题广场 >

订单表order_table全部记录如下,查询连续3天下单的

[单选题]
订单表order_table全部记录如下,查询连续3天下单的customer_name,比如zhangsan在12.1、12.2号和12.3号连续3天下单过,以下不符合预期的是()?
+----+----------+--------+---------+---------------+------------+
| id | order_id | sku_id | buy_num | customer_name | buy_date   |
+----+----------+--------+---------+---------------+------------+
|  1 |   560001 |   1001 |       2 | zhangsan      | 2021-12-01 |
|  2 |   560001 |   1002 |       1 | lisi          | 2021-12-01 |
|  3 |   560002 |   1001 |       1 | zhangsan      | 2021-12-02 |
|  4 |   560003 |   1003 |       2 | zhangsan      | 2021-12-03 |
|  5 |   560004 |   1002 |       3 | lisi          | 2021-12-02 |
+----+----------+--------+---------+---------------+------------+
5 rows in set (0.00 sec)
  • SELECT customer_name
    FROM (
        SELECT  
        customer_name,
        buy_date,
        LEAD(buy_date,1) OVER(partition by customer_name order by buy_date) as next1_buy_date,
        LEAD(buy_date,2) OVER(partition by customer_name order by buy_date) as next2_buy_date
        FROM
        order_table 
    )t1
    WHERE 
    TIMESTAMPDIFF(DAY,buy_date,next1_buy_date) = 1 
    and TIMESTAMPDIFF(DAY,buy_date,next2_buy_date) = 2 ;
  • SELECT customer_name
    FROM (
        SELECT  
        customer_name,
        buy_date,
        LAG(buy_date,1) OVER(partition by customer_name order by buy_date) as next1_buy_date,
        LEAD(buy_date,1) OVER(partition by customer_name order by buy_date) as next2_buy_date
        FROM
        order_table 
    )t1
    WHERE 
    TIMESTAMPDIFF(DAY,buy_date,next1_buy_date) = -1 
    and TIMESTAMPDIFF(DAY,buy_date,next2_buy_date) = -1 ;
  • SELECT customer_name
    FROM (
        SELECT  
        customer_name,
        buy_date,
        LAG(buy_date,1) OVER(partition by customer_name order by buy_date) as next1_buy_date,
        LAG(buy_date,2) OVER(partition by customer_name order by buy_date) as next2_buy_date
        FROM
        order_table 
    )t1
    WHERE 
    TIMESTAMPDIFF(DAY,buy_date,next1_buy_date) = -1 
    and TIMESTAMPDIFF(DAY,buy_date,next2_buy_date) = -2 ;
  • SELECT customer_name
    FROM (
        SELECT  
        customer_name,
        buy_date,
        LEAD(buy_date,1) OVER(partition by customer_name order by buy_date) as next1_buy_date,
        LAG(buy_date,1) OVER(partition by customer_name order by buy_date) as next2_buy_date
        FROM
        order_table 
    )t1
    WHERE 
    TIMESTAMPDIFF(DAY,buy_date,next1_buy_date) = 1 
    and TIMESTAMPDIFF(DAY,buy_date,next2_buy_date) = -1 ;
lead是排序向后指定某条数据,lag是排序后向前指定某条数据,b选项里计算值应该是-1,1。而不是-1,-1
发表于 2025-07-14 10:36:53 回复(0)
选项A 正确


发表于 2025-08-31 10:58:13 回复(2)

为了找出连续3天下单的customer_name,并判断哪个选项不符合预期,我们首先分析数据表order_table的记录:

id order_id sku_id buy_num customer_name buy_date
1 560001 1001 2 zhangsan 2021-12-01
2 560001 1002 1 lisi 2021-12-01
3 560002 1001 1 zhangsan 2021-12-02
4 560003 1003 2 zhangsan 2021-12-03
5 560004 1002 3 lisi 2021-12-02
  • zhangsan 在 2021-12-01、2021-12-02 和 2021-12-03 下单,是连续3天下单。

  • lisi 在 2021-12-01 和 2021-12-02 下单,只有连续2天,不符合连续3天的条件。

因此,预期的查询结果应只返回 customer_name 为 zhangsan。

接下来,分析每个选项的 SQL 查询。所有选项都使用窗口函数(LEAD 或 LAG)按 customer_name 分区并按 buy_date 排序:

  • LEAD(buy_date, n) OVER(...) 获取当前行之后第 n 行的日期。

  • LAG(buy_date, n) OVER(...) 获取当前行之前第 n 行的日期。

  • TIMESTAMPDIFF(DAY, start, end) 计算 end - start 的天数差(正值表示 end 在 start 之后,负值表示在之前)。

选项 A 分析

sql
复制
下载
SELECT customer_name FROM ( SELECT customer_name, buy_date, LEAD(buy_date,1) OVER(partition by customer_name order by buy_date) as next1_buy_date, LEAD(buy_date,2) OVER(partition by customer_name order by buy_date) as next2_buy_date FROM order_table )t1 WHERE TIMESTAMPDIFF(DAY,buy_date,next1_buy_date) = 1 and TIMESTAMPDIFF(DAY,buy_date,next2_buy_date) = 2 ;
  • 逻辑:对于每个客户,取当前行的日期(buy_date)、后一行的日期(next1_buy_date)和后第二行的日期(next2_buy_date)。条件要求:

    • next1_buy_date - buy_date = 1(即后一天)

    • next2_buy_date - buy_date = 2(即后两天)

  • 这表示当前行、后一行和后第二行构成连续三天(如当前行是第1天,后一行是第2天,后第二行是第3天)。

  • 数据验证:

    • zhangsan:

      • 第一行 (2021-12-01): next1_buy_date = 2021-12-02(id=3), next2_buy_date = 2021-12-03(id=4)

        • TIMESTAMPDIFF(DAY, '2021-12-01', '2021-12-02') = 1(满足)

        • TIMESTAMPDIFF(DAY, '2021-12-01', '2021-12-03') = 2(满足),此行满足条件。

      • 其他行(如2021-12-02 或 2021-12-03)的 next2_buy_date 可能为 NULL,不满足条件。

    • lisi:

      • 所有行(如2021-12-01 的 next2_buy_date 为 NULL)不满足条件。

  • 结果:返回 zhangsan,符合预期。

选项 B 分析

sql
复制
下载
SELECT customer_name FROM ( SELECT customer_name, buy_date, LAG(buy_date,1) OVER(partition by customer_name order by buy_date) as next1_buy_date, LEAD(buy_date,1) OVER(partition by customer_name order by buy_date) as next2_buy_date FROM order_table )t1 WHERE TIMESTAMPDIFF(DAY,buy_date,next1_buy_date) = -1 and TIMESTAMPDIFF(DAY,buy_date,next2_buy_date) = -1 ;
  • 逻辑:对于每个客户,取当前行的日期(buy_date)、前一行的日期(next1_buy_date,即 LAG(1)) 和后一行的日期(next2_buy_date,即 LEAD(1))。条件要求:

    • next1_buy_date - buy_date = -1(即前一天)

    • next2_buy_date - buy_date = -1(即后一天?但 LEAD 应为正差)

  • 问题:next2_buy_date 是 LEAD(1)(后一行日期),因此 next2_buy_date - buy_date 应大于或等于 0(未来日期),不可能为负值(-1)。条件要求两个差值都为 -1,但 LEAD 部分永远无法满足。

  • 数据验证:

    • zhangsan:

      • 第一行 (2021-12-01): next1_buy_date(LAG)为 NULL(无前一行),next2_buy_date(LEAD)= 2021-12-02

        • TIMESTAMPDIFF(DAY, '2021-12-01', NULL) 为 NULL(不满足 -1)

        • TIMESTAMPDIFF(DAY, '2021-12-01', '2021-12-02') = 1(不为 -1),不满足。

      • 第二行 (2021-12-02): next1_buy_date = 2021-12-01, next2_buy_date = 2021-12-03

        • TIMESTAMPDIFF(DAY, '2021-12-02', '2021-12-01') = -1(满足)

        • TIMESTAMPDIFF(DAY, '2021-12-02', '2021-12-03') = 1(不为 -1),不满足。

      • 第三行 (2021-12-03): next1_buy_date = 2021-12-02, next2_buy_date 为 NULL

        • TIMESTAMPDIFF(DAY, '2021-12-03', '2021-12-02') = -1(满足)

        • TIMESTAMPDIFF(DAY, '2021-12-03', NULL) 为 NULL(不满足 -1),不满足。

    • lisi:同样无行满足条件。

  • 结果:无任何行满足条件,返回空结果。但 zhangsan 应被返回,不符合预期。

选项 C 分析

sql
复制
下载
SELECT customer_name FROM ( SELECT customer_name, buy_date, LAG(buy_date,1) OVER(partition by customer_name order by buy_date) as next1_buy_date, LAG(buy_date,2) OVER(partition by customer_name order by buy_date) as next2_buy_date FROM order_table )t1 WHERE TIMESTAMPDIFF(DAY,buy_date,next1_buy_date) = -1 and TIMESTAMPDIFF(DAY,buy_date,next2_buy_date) = -2 ;
  • 逻辑:对于每个客户,取当前行的日期(buy_date)、前一行的日期(next1_buy_date,即 LAG(1)) 和前第二行的日期(next2_buy_date,即 LAG(2))。条件要求:

    • next1_buy_date - buy_date = -1(即前一天)

    • next2_buy_date - buy_date = -2(即前两天)

  • 这表示当前行是连续三天的第3天(前一行是第2天,前第二行是第1天)。

  • 数据验证:

    • zhangsan:

      • 第三行 (2021-12-03): next1_buy_date = 2021-12-02(id=3), next2_buy_date = 2021-12-01(id=1)

        • TIMESTAMPDIFF(DAY, '2021-12-03', '2021-12-02') = -1(满足)

        • TIMESTAMPDIFF(DAY, '2021-12-03', '2021-12-01') = -2(满足),此行满足条件。

      • 其他行(如2021-12-01 或 2021-12-02)的 next2_buy_date 可能为 NULL,不满足。

    • lisi:所有行(如2021-12-02 的 next2_buy_date 为 NULL)不满足条件。

  • 结果:返回 zhangsan,符合预期。

选项 D 分析

sql
复制
下载
SELECT customer_name FROM ( SELECT customer_name, buy_date, LEAD(buy_date,1) OVER(partition by customer_name order by buy_date) as next1_buy_date, LAG(buy_date,1) OVER(partition by customer_name order by buy_date) as next2_buy_date FROM order_table )t1 WHERE TIMESTAMPDIFF(DAY,buy_date,next1_buy_date) = 1 and TIMESTAMPDIFF(DAY,buy_date,next2_buy_date) = -1 ;
  • 逻辑:对于每个客户,取当前行的日期(buy_date)、后一行的日期(next1_buy_date,即 LEAD(1)) 和前一行的日期(next2_buy_date,即 LAG(1))。条件要求:

    • next1_buy_date - buy_date = 1(即后一天)

    • next2_buy_date - buy_date = -1(即前一天)

  • 这表示当前行是连续三天的中间一天(前一行是第1天,后一行是第3天)。

  • 数据验证:

    • zhangsan:

      • 第二行 (2021-12-02): next1_buy_date = 2021-12-03(id=4), next2_buy_date = 2021-12-01(id=1)

        • TIMESTAMPDIFF(DAY, '2021-12-02', '2021-12-03') = 1(满足)

        • TIMESTAMPDIFF(DAY, '2021-12-02', '2021-12-01') = -1(满足),此行满足条件。

      • 其他行(如2021-12-01 或 2021-12-03)的 next1_buy_date 或 next2_buy_date 可能为 NULL,不满足。

    • lisi:所有行不满足条件。

  • 结果:返回 zhangsan,符合预期。

不符合预期的选项

  • 选项 A、C、D 都能正确返回 zhangsan(尽管匹配的行不同,但最终结果一致)。

  • 选项 B 无法返回任何结果,因为条件 TIMESTAMPDIFF(DAY,buy_date,next2_buy_date) = -1 中的 next2_buy_date 是 LEAD(1)(后一行日期),其差值应为正数(如 1),但条件要求为 -1(负数),逻辑矛盾,永远无法满足。因此,选项 B 不符合预期。

结论:不符合预期的是选项 B。

开启新对话
深度思考 (R1)
联网搜索

发表于 2025-07-03 19:48:34 回复(1)
我合计A也没问题啊
发表于 2025-10-19 16:59:14 回复(0)
LEG与LEAD是获取同一结果集中其他行数据的窗口函数。 LEG是向前获取,LEAD是取当前行后面的
发表于 2025-09-24 17:18:58 回复(0)
TIMESTAMPDIFF(DAY,buy_date,next1_buy_date) = -1
and TIMESTAMPDIFF(DAY,buy_date,next2_buy_date) = -1
B选项的这个,明显不对呀!
应该是C才对把。
发表于 2025-06-30 09:20:46 回复(2)