首页 > 试题广场 >

某宝店铺连续2天及以上购物的用户及其对应的天数

[编程题]某宝店铺连续2天及以上购物的用户及其对应的天数
  • 热度指数:42574 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
11月结束后,小牛同学需要对其在某宝的网店就11月份用户交易情况和产品情况进行分析以更好的经营小店。
11月份销售数据表sales_tb如下(其中,sales_date表示销售日期,user_id指用户编号,item_id指货号,sales_num表示销售数量,sales_price表示结算金额):
sales_date user_id item_id sales_num sales_price
2021-11-01 1 A001 1 90
2021-11-01
2 A002 2 220
2021-11-01
2 B001 1 120
2021-11-02
3 C001 2 500
2021-11-02
4 B001 1 120
2021-11-03
5 C001 1 240
2021-11-03
6 C002 1 270
2021-11-04
7 A003 1 180
2021-11-04
8 B002 1 140
2021-11-04
9 B001 1 125
2021-11-05
10 B003 1 120
2021-11-05
10 B004 1 150
2021-11-05
10 A003 1 180
2021-11-06
11 B003 1 120
2021-11-06
10 B004 1 150
请你统计连续2天及以上在该店铺购物的用户及其对应的次数(若有多个用户,按user_id升序排序),以上例子的输出结果如下:
user_id days_count
10 2

示例1

输入

drop table if exists sales_tb;
CREATE TABLE sales_tb(
sales_date date NOT NULL,
user_id int(10) NOT NULL,
item_id char(10) NOT NULL,
sales_num int(10) NOT NULL,
sales_price int(10) NOT NULL
);

INSERT INTO sales_tb VALUES('2021-11-1', 1, 'A001',  1, 90);
INSERT INTO sales_tb VALUES('2021-11-1', 2, 'A002',  2, 220);
INSERT INTO sales_tb VALUES('2021-11-1', 2, 'B001',  1, 120);
INSERT INTO sales_tb VALUES('2021-11-2', 3, 'C001',  2, 500);
INSERT INTO sales_tb VALUES('2021-11-2', 4, 'B001',  1, 120);
INSERT INTO sales_tb VALUES('2021-11-3', 5, 'C001',  1, 240);
INSERT INTO sales_tb VALUES('2021-11-3', 6, 'C002',  1, 270);
INSERT INTO sales_tb VALUES('2021-11-4', 7, 'A003',  1, 180);
INSERT INTO sales_tb VALUES('2021-11-4', 8, 'B002',  1, 140);
INSERT INTO sales_tb VALUES('2021-11-4', 9, 'B001',  1, 125);
INSERT INTO sales_tb VALUES('2021-11-5', 10, 'B003',  1, 120);
INSERT INTO sales_tb VALUES('2021-11-5', 10, 'B004',  1, 150);
INSERT INTO sales_tb VALUES('2021-11-5', 10, 'A003',  1, 180);
INSERT INTO sales_tb VALUES('2021-11-6', 11, 'B003',  1, 120);
INSERT INTO sales_tb VALUES('2021-11-6', 10, 'B004',  1, 150);

输出

10|2

select user_id,(count(*)+1) days_count

from (

    select user_id, sales_date,

    lead(sales_date,1)over(partition by user_id order by sales_date) late_date

    from sales_tb

)t1

where datediff(late_date,sales_date) = 1

group by user_id,sales_date

order by user_id;

发表于 2024-12-04 16:17:04 回复(0)
select user_id,count(distinct sales_date) as ck
from sales_tb
group by user_id
having count(distinct sales_date) >= 2
order by user_id
这明显错了的也能过

发表于 2024-09-29 22:27:28 回复(0)
with t0 as(
select
sales_date,
user_id
from 
sales_tb
group by 1,2)

select

user_id,
count(user_id) as days_count

from(

select
date1,
user_id,
DATE_ADD(date1, INTERVAL -rk DAY) as date2


from(
select
sales_date as date1,
user_id,
row_number()over(partition by user_id order by sales_date) as rk

from
t0) as t1
) as t2

group by 1
having count(user_id)>1

发表于 2024-09-27 15:03:22 回复(0)
with t1 as (
select user_id, sales_date,
dense_rank()over(partition by user_id order by sales_date) rk
from sales_tb
)
,t2 as (
select user_id, sales_date,
dense_rank()over(partition by user_id, date_sub(sales_date, interval rk day) order by sales_date) days
from t1
)

select user_id, max(days) days_count from t2
group by user_id
having days_count >= 2
order by user_id


发表于 2024-09-24 15:05:38 回复(0)
-- 第一步:从 sales_tb 表中获取唯一的 sales_date 和 user_id
WITH
    users_tb AS (
        SELECT DISTINCT
            sales_date,
            user_id
        FROM
            sales_tb
    ),

-- 第二步:为每个用户按 sales_date 生成行号 user_rank
    rank_users_tb AS (
        SELECT
            sales_date,
            user_id,
            ROW_NUMBER() OVER (
                PARTITION BY
                    user_id
                ORDER BY
                    sales_date
            ) user_rank
        FROM
            users_tb
    ),

-- 第三步:计算每个用户从第一个销售日期开始的 beg_dt
    date_users_tb AS (
        SELECT
            sales_date,
            user_id,
            DATE_SUB(sales_date, INTERVAL user_rank DAY) beg_dt
        FROM
            rank_users_tb
    ),

-- 第四步:为每个用户按 beg_dt 生成新的行号 days
    day_users_tb AS (
        SELECT
            sales_date,
            user_id,
            ROW_NUMBER() OVER (PARTITION BY user_id, beg_dt ORDER BY sales_date) days
        FROM
            date_users_tb
    )

-- 最终查询:计算每个用户的最大连续销售天数,且这些天数要大于等于2
SELECT 
    user_id,
    MAX(days) AS days_count
FROM day_users_tb
WHERE days >= 2
GROUP BY user_id;

发表于 2024-07-19 14:26:03 回复(0)
with date_table as
    (select sales_date, user_id
        from sales_tb
      group by sales_date, user_id)

select a.user_id, count(a.sales_date) days_count
    from date_table a left join date_table b
    on (a.sales_date = date_sub(b.sales_date, interval 1 day) and a.user_id = b.user_id)
    group by user_id
    having sum(b.sales_date is not null) > 0

思路:先建立一个CTE,包含不重不漏的购买日期, user_id字符
将两个CTE做left_join, 条件是右边的CTE的日期是左边的CTE + 1
这时候按user_id group 之后, 可以统计出天数和右边的CTE非空的数量,只保留不全为空的用户
发表于 2024-07-13 22:30:43 回复(0)
-- 思路:所有用户购买过的日期,根据购买日期dense_rank再使用做差法统计出连续购买的日期分组,用户下有几个相同的做差日期,就是连续工作了几天。再筛选≥2天的

select user_id,days_count
from (--
select
user_id,day_,count(day_) days_count
from (--
select user_id,sales_date
,date_sub(sales_date,interval day_dense_rank day) day_
,当日购物次数
from (--
select
user_id,sales_date
,dense_rank() over(partition by user_id order by sales_date asc) day_dense_rank
,当日购物次数
from (--
select user_id,sales_date,count(user_id) 当日购物次数
from sales_tb
group by user_id,sales_date
) a) b) c
group by user_id,day_
having count(day_)>=2) t
;

发表于 2024-07-11 14:43:40 回复(0)
select user_id,max(days_count) days_count
from(
select user_id,count(*) days_count,dt
from(
select distinct sales_date,user_id
,sales_date-dense_rank() over(partition by user_id order by sales_date) dt
from sales_tb) t1
group by user_id,dt
having count(*)>=2) t2
group by user_id,dt
order by 1 

发表于 2024-06-07 10:03:16 回复(0)
可算是会一题了
WITH A AS(
    SELECT user_id, sales_date - rk AS cd
    FROM(
    SELECT DISTINCT user_id, sales_date, DENSE_RANK()OVER(PARTITION BY user_id ORDER BY sales_date ASC) AS rk 
    FROM sales_tb
    ) AS subq
), B AS(
    SELECT user_id, COUNT(*) AS cc
    FROM A
    GROUP BY user_id, cd
)
SELECT * 
FROM B 
WHERE cc >= 2
ORDER BY user_id


发表于 2024-04-29 12:44:53 回复(0)
select 
    user_id,
    count(sales_date) days_cnt
from(
    select
        user_id,
        sales_date,
        sales_date - interval (rk-1) day as fday
    from(
        select
            distinct
            user_id,
            sales_date,
            dense_rank() over(partition by user_id order by sales_date) as rk
        from
            sales_tb
    )t1
)t2
group by 
    user_id,
    fday
having 
    days_cnt >= 2
order by
    user_id

编辑于 2024-04-18 10:06:33 回复(0)
思路:开窗对每一个日期进行排序得到位次,然后日期和位次做差(date_sub)得到新的日期,若新日期相等,则相等的日期个数即为连续登录天数
比如日期11-01,11-02,11-03,    11-05,11-06
排序得到他们的位次为1,2,3,     4,5
做差得到日期10-31,10-31,10-31,    11-1,11-1
因此10-31有三个,表明3天连续登录
with
t as # 用户分组,按照登陆日期开窗排序得到每一个日期的位次
(
select
    uid
    ,dt
    , dense_rank() over(partition by uid order by dt) as rk
from 
   (select distinct *  # 去重,因为用户可能一天登录几次
   from 
        (select sales_date as dt, user_id as uid 
        from sales_tb 
        where date_format(sales_date, '%Y-%m')='2021-11')t #筛选出每一个用户的登录日期
    )t
),
t1 as  # 日期和位次做差,得到一个新的日期day_tag
(
select 
    uid
    , date_sub(dt, interval rk day) as day_tag 
from t
),
t2 as # 按照用户和day_tag分组,并计数相同day_tag有多少(连续登录天数)
(
select 
    uid, count(day_tag) as day_tag
from t1
group by uid, day_tag
)

# 按照用户分组,max()得到最大的连续登录天数
select uid, max(day_tag) 
from t2
group by uid
having max(day_tag)>1;


发表于 2024-02-14 17:06:17 回复(0)
select user_id, max(days_count) as days_count
from (
select user_id, count(date_sub(sales_date, interval rk day)) as days_count
from (
select distinct user_id, sales_date, dense_rank() over(partition by user_id order by sales_date asc) as rk
from sales_tb ) a
group by user_id
having days_count >= 2
) a
group by user_id
order by user_id asc
编辑于 2024-01-22 14:46:27 回复(0)
SELECT user_id,
count(distinct st1.sales_date)+1 as days_count
from sales_tb st1 join sales_tb st2 using(user_id)
where  DATEDIFF(st2.sales_date,st1.sales_date)=1
group by user_id order by user_id asc;
这个题目还是有点意思,容易出错
发表于 2024-01-15 23:02:00 回复(0)
with t1 as (
    select  distinct user_id,sales_date
    from sales_tb
)
,
t2 as (
    select  user_id,
            row_number() over (partition by user_id order by sales_date) rk 
    from t1
)
select user_id,max(rk)
from t2 
where rk>=2
group by user_id

发表于 2023-10-09 18:47:25 回复(1)
select uf,count(n)
from 
(select (row_number() over (order by sales_date) - row_number() over (partition by uf order by sales_date)) as n,
uf,sales_date
 from(
select distinct
    user_id as uf,
    sales_date
from
    sales_tb
order by
    sales_date) as t1) t2
group by uf
having count(n)>=2

发表于 2023-08-22 11:33:12 回复(0)
select user_id,cnt from 
(
select
user_id,
date_sub(sales_date, interval rn day) sub_day,
count(1) cnt
from
(
select 
user_id,
sales_date,
row_number()over(partition by user_id order by sales_date) rn
from (select user_id, sales_date from sales_tb group by user_id, sales_date) t1
 ) t2
group by user_id, date_sub(sales_date, interval rn day)
) t3
where cnt>=2
order by 1;

发表于 2023-08-11 11:57:56 回复(0)
select
    t.user_id,
    max(t.cnt) as days_count
from
    (
        select
            user_id,
            dense_rank() over (
                partition by
                    user_id
                order by
                    sales_date
            ) as cnt
        from
            sales_tb
    ) t
where
    t.cnt >= 2
group by
    user_id

发表于 2023-08-11 00:11:52 回复(0)
-- step6:得到连续天最长的一组的用户编号和连续天数,最后根据用户编号升序排序
select user_id,counts as days_count
from (
	-- step5:考虑到可能有多组连续天,找到连续天最长的一组,用row_number来排序
	select *,row_number()over(partition by user_id order by counts desc) rk
	from (
		-- step4:根据差值日期和用户编号分组,计算每组的天数,天数>= 2的,则为连续2天及2天以上的
		select date_diff,user_id,count(distinct sales_date) counts
		from (
			-- step3:用销售日期减去辅助列,得到差值日期,(思路:如果差值日期相同,则代表相同的几个差值日期为连续天)
			select date_sub(sales_date,interval rk_1 day) as date_diff,user_id,sales_date
			from (
				-- step2:用row_number,添加辅助列
				select *,row_number()over(partition by user_id order by sales_date) rk_1
				from (
					-- step1:去重 用户编号 和 销售日期
					select distinct sales_date,user_id
					from sales_tb
				) a
			) a
		) a
		group by date_diff,user_id
		having count(distinct sales_date) >= 2
	) a
) a
where rk = 1
order by user_id

发表于 2023-05-31 10:16:37 回复(0)