首页 > 试题广场 >

牛客的课程订单分析(四)

[编程题]牛客的课程订单分析(四)
  • 热度指数:66242 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

有很多同学在牛客购买课程来学习,购买会产生订单存到数据库里

有一个订单信息表(order_info),简况如下:

id user_id product_name
status
client_id
date
1 557336
C++
no_completed
1 2025-10-10
2 230173543
Python
completed
2 2025-10-12
3 57 JS
completed
3 2025-10-23
4 57 C++
completed
3 2025-10-23
5 557336
Java
completed
1 2025-10-23
6 57 Java
completed
1 2025-10-24
7 557336
C++
completed
1 2025-10-25
8 557336
Python
completed
1 2025-10-25

1行表示user_id557336的用户在2025-10-10的时候使用了client_id1的客户端下了C++课程的订单,但是状态为没有购买成功。

2行表示user_id230173543的用户在2025-10-12的时候使用了client_id2的客户端下了Python课程的订单,状态为购买成功。

。。。

最后1行表示user_id557336的用户在2025-10-25的时候使用了client_id1的客户端下了Python课程的订单,状态为购买成功。

请你写出一个sql语句查询在2025-10-15以后,如果有一个用户下单2个以及2个以上状态为购买成功的C++课程或Java课程或Python课程,那么输出这个用户的user_id以及满足前面条件的第一次购买成功的C++课程或Java课程或Python课程的日期first_buy_date,以及2025-10-15以后购买成功的C++课程或Java课程或Python课程的次数cnt,并且输出结果按照user_id升序排序,以上例子查询结果如下:

user_id first_buy_date cnt
57 2025-10-23 2
557336 2025-10-23 3

解析:

id为46的订单满足以上条件,输出57id为4的订单为第一次购买成功,输出first_buy_date为2025-10-23,总共成功购买了2;

id为578的订单满足以上条件,输出557336id为5的订单为第一次购买成功,输出first_buy_date为2025-10-23,总共成功购买了3;

示例1

输入

drop table if exists order_info;
CREATE TABLE order_info (
id int(4) NOT NULL,
user_id int(11) NOT NULL,
product_name varchar(256) NOT NULL,
status varchar(32) NOT NULL,
client_id int(4) NOT NULL,
date date NOT NULL,
PRIMARY KEY (id));

INSERT INTO order_info VALUES
(1,557336,'C++','no_completed',1,'2025-10-10'),
(2,230173543,'Python','completed',2,'2025-10-12'),
(3,57,'JS','completed',3,'2025-10-23'),
(4,57,'C++','completed',3,'2025-10-23'),
(5,557336,'Java','completed',1,'2025-10-23'),
(6,57,'Java','completed',1,'2025-10-24'),
(7,557336,'C++','completed',1,'2025-10-25'),
(8,557336,'Python','completed',1,'2025-10-25');

输出

57|2025-10-23|2
557336|2025-10-23|3
WITH t as (
SELECT
    user_id,
    min( date ) AS first_buy_date,
    count( product_name ) AS cnt
FROM
    order_info
    WHERE date>'2025-10-15' and product_name!='JS' and status='completed'
GROUP BY user_id  
ORDER BY user_id asc ) SELECT * from  t where cnt>1
发表于 2024-11-05 15:43:52 回复(0)
select 
    user_id,
    min(date) first_buy_date,
    count(*) cnt
from
    order_info
where
    user_id in (
        select
            user_id
        from
            order_info
        where
            date > "2025-10-15"
            and status = "completed"
            and product_name in ("C++", "Python", "Java")
        group by
            user_id
        having
            count(*) > 1
    )
    and date > "2025-10-15"
    and status = "completed"
    and product_name in ("C++", "Python", "Java")
group by 
    user_id
order by 
    user_id
先筛选出符合条件的用户,再选择符合购买条件的数据,最后对用户进行分组统计

发表于 2024-10-23 11:38:30 回复(0)
这题答案有错误吧,题目中写要所有日期里购买成功的次数cnt🤨🤨🤨
SELECT user_id,min(date) first_buy_date,
(
    SELECT count(user_id)
    FROM order_info
    WHERE status='completed' AND product_name IN ('Python','C++','Java') AND user_id=o1.user_id
) cnt
FROM order_info o1
WHERE status='completed' AND date>'2025-10-15' AND product_name IN ('Python','C++','Java')
GROUP BY user_id
HAVING count(user_id)>=2
ORDER BY user_id
发表于 2024-09-20 10:35:43 回复(0)

要用到子查询和group by + having

select user_id, min(date) as first_date, count(id) as cnt
from order_info 
where 
product_name in ('C++', 'Java', 'Python')
and date >= '2025-10-15'
and status = 'completed'
and user_id in (
    select user_id
    from order_info 
    where 
    product_name in ('C++', 'Java', 'Python')
    and date >= '2025-10-15'
    and status = 'completed'
    group by user_id
    having count(id) >= 2
)
group by user_id
order by user_id asc
发表于 2024-08-14 10:40:41 回复(0)
本来用内连接写的,但是其实繁琐了
select t1.user_id as user_id,
min(t1.date) as first_buy_date,
t2.cnt as cnt
from order_info as t1

inner join
(select user_id, count(id) as cnt
from order_info
where datediff(date, '2025-10-15')>0
and product_name in ('C++', 'Java', 'Python')
and status='completed'
group by user_id
having count(id)>1
order by user_id) as t2
on t1.user_id=t2.user_id

where datediff(date, '2025-10-15')>0
and product_name in ('C++', 'Java', 'Python')
and status='completed'
group by t1.user_id
order by t1.user_id;
后来发现,按user_id分组之后,可以一步到位同时查询min(date)和count(id)
select user_id, min(date) as first_buy_date, count(id) as cnt
from order_info
where datediff(date, '2025-10-15')>0
and product_name in ('C++', 'Java', 'Python')
and status='completed'
group by user_id
having count(id)>1
order by user_id;



发表于 2024-07-28 15:22:00 回复(0)
select
user_id,min(date),count(*)
from (
select
user_id,date,row_number()over(partition by user_id order by date) rn,count(user_id)over(partition by user_id) ct
from order_info
where date>='2025-10-15'
and status='completed'
and product_name in ('C++','Python','Java')
)t
where ct>1
group by user_id
order by user_id
;

发表于 2024-07-19 16:15:03 回复(0)
针对目前的题目设置,给出一个可行解如下:



实际上,题目所给信息有误,所有的有效日期其实都是在‘2025-10-15’之后的,因此可以直接通过min(date)来给出first_buy_date;
若修正这一缺陷,在题目中增设在该日期之前也购买成功的记录,则需要多一步——筛选出对应日期之后的记录
select
    *
from
    order_info
where
     `date` > '2025-10-15' 
再执行第一版的操作即可;
最终的完整语句为:
with a as(
select
    *
from
    order_info
where
     `date` > '2025-10-15' 
     )
SELECT
    user_id,
    MIN(`date`) as first_buy_date,
    COUNT(id) as cnt
FROM
    a
WHERE 
    product_name IN ('C++','Java','Python') 
    AND `status` = 'completed'
GROUP BY
    user_id
HAVING COUNT(id) >=2
ORDER BY user_id ASC;

发表于 2024-07-10 11:11:30 回复(1)
select
    user_id,
    min(date) first_buy_date,
    count(id) cnt
from order_info
where date>'2025-10-15' and status='completed' and product_name in ('C++','Java','Python')
group by user_id
having count(id)>=2
order by user_id
发表于 2024-06-11 22:35:45 回复(0)
select user_id,min(date) as first_buy_date, rk as cnt
from(
select *,count(*) over(partition by user_id) rk
from order_info
where datediff(date,"2025-10-15")>0
      and product_name in ("C++","Java","Python")
      and status="completed") t
      where rk>1
      group by user_id
      order by 1

发表于 2024-05-29 13:47:19 回复(0)
select user_id,min(date) as first_buy_date,count(*) as cnt
from order_info
where status = 'completed'
and product_name in ('C++','Java','Python')
and date > '2025-10-15'
group by user_id
having cnt >= 2
order by user_id;

发表于 2024-04-25 09:48:04 回复(0)
select user_id
,min(date)
,count(user_id)
from order_info
where user_id in (select user_id
from (select user_id
,count(status)
from order_info
where date>'2025-10-15' and status='completed' and product_name in ('C++','Java','Python')
group by 1
having 2>=2) a) and status='completed' and product_name in ('C++','Java','Python') and date>'2025-10-15'
group by 1
having count(user_id) > 1
order by user_id

一直嵌套出来的 比较笨的解题方法
发表于 2024-04-11 23:22:25 回复(0)
这题目写得好难懂.. 我以为first_buy_date是第一次成功购买C++,Python,Java的时间..结果是10-15之后第一次购买的时间(这还能叫第一次购买吗狗头


发表于 2024-03-25 18:36:55 回复(0)
with t as (
select user_id,min(date) as first_buy_date,count(user_id)  as cnt from order_info
where date >= "2025-10-15" and status = "completed" 
and product_name in ("C++","Java","Python")
group by user_id
having count(user_id) >= 2
order by user_id)

select * from t;

发表于 2024-03-14 16:25:45 回复(0)
select c.uid,u.fst,c.cnt from
(select user_id as uid,count(*) as cnt from order_info
where status='completed'
and product_name in ('C++','Java','Python')
and datediff(date,'2025-10-15')>0
group by uid) as c #所有用户的购买次数
inner join
(select user_id as uid,min(date) as fst from order_info
where status='completed'
and product_name in ('C++','Java','Python')
and datediff(date,'2025-10-15')>0
group by uid
having count(uid)>1) as u #2025-10-15以后买2次的用户和最早购买日期
on c.uid=u.uid
order by c.uid;
简化
select user_id as uid,min(date),count(user_id) as fst from order_info
where status='completed'
and product_name in ('C++','Java','Python')
and datediff(date,'2025-10-15')>0
group by uid
having count(uid)>1
order by uid;


发表于 2024-01-13 18:01:49 回复(0)
select user_id,min(date) first_buy_date,count(distinct product_name) cnt 
from order_info 
where date>'2025-10-15'
and product_name in ('Java','Python','C++')
and status='completed'
group by user_id
having count(distinct product_name)>=2
order by user_id

发表于 2024-01-02 10:07:23 回复(0)
select
    user_id,
    date first_buy_date,
    cnt
from
     (select *,count(*)over(partition by user_id) cnt,rank()over(partition by user_id order by date)rk from order_info
    where product_name in ('C++', 'Java', 'Python')
    and date > '2025-10-15'
    and status = 'completed')g
   where cnt>=2 and rk=1
   order by user_id



select
    user_id,
    min(date) first_buy_date,
    min(cnt)
from
     (select *,count(*)over(partition by user_id) cnt from order_info
    where product_name in ('C++', 'Java', 'Python')
    and date > '2025-10-15'
    and status = 'completed')g
   where cnt>=2
   group by user_id
   order by user_id


发表于 2023-11-24 10:49:12 回复(0)
和方法1相比,方法2有趣的多,min和count的灵活用法也更符合题目的难度,尤其是min()中嵌套case when的用法,我也是第一次尝试,着实有趣的很
# 方法1 所有日期里购买成功的课程的次数cnt不包含‘2025-10-15’之前的,是标准答案,但个人感觉不符题意
select user_id,
min(date) as first_buy_date,
count(*) as cnt
from order_info
where product_name in ('C++','Java','Python') 
and status='completed' and date>'2025-10-15'
group by user_id
having cnt>=2
order by user_id

# 方法2 如果所有日期里购买成功的课程的次数cnt包含‘2025-10-15’之前的,与标准答案不符,但更符题意
select user_id,
min(case when date > '2025-10-15' then date else null end) as first_buy_date,
count(*) as cnt
from order_info
where product_name in ('C++','Java','Python') 
and status='completed' 
group by user_id
having count(date>'2025-10-15'&nbs***bsp;null)>=2
order by user_id


发表于 2023-10-16 15:10:38 回复(0)
select * from 

(select user_id,min(date) from order_info
where status='completed' and date>'2025-10-15' and product_name in ('C++','Java','Python')
group by user_id) a

inner join 

(select user_id,count(user_id) as cs from order_info
where status='completed' and date>'2025-10-15' and product_name in ('C++','Java','Python')
group by user_id) b using(user_id)
where cs>=2
order by user_id

发表于 2023-08-02 13:05:44 回复(0)
题目长到匪夷所思
发表于 2023-06-07 15:52:25 回复(0)