请教大家一个关于订单统计 sql 的问题

2020-04-23 10:06:06 +08:00
 liubx

现在有个功能需要统计每个用户的首单。自己写的 sql 不太满意,希望大家能指点下。

这是我写的 sql

SELECT * FROM order WHERE create_time IN (
		SELECT min( create_time ) create_time FROM
			order WHERE
			order_status IN ( 'PRE_DELIVER', 'PRE_ACCEPT', 'AFTER_DELIVER' ) 
			AND user_id in (1,2,3,4) AND deleted = 0 GROUP BY user_id 
	) 
GROUP BY user_id

我是先查询出每个用户第一单的时间,在通过时间去查询对应的订单。

但想不出怎么去优化,只能请教下大家,希望能给一些思路

4362 次点击
所在节点    MySQL
39 条回复
liubx
2020-04-23 11:21:29 +08:00
@lifespy 谢谢,这个方法不错啊
wuzhizuiguo
2020-04-23 11:24:16 +08:00
如果 order 表的 id 是 bigint 然后是自增的, 根据 user_id 分组找到 id 最小的(时间应该也是最早的)
select id from orders group by user_id order by id asc
//找出这些订单
select * from orders where id in( select o.id from orders o group by o.user_id order by o.id asc) and ...
lifespy
2020-04-23 11:25:49 +08:00
@liubx #21 是的,因为根据你的描述以及业务。订单这个东西一旦创建时不会变的,所以可以单独存储
DoUSeeMe
2020-04-23 11:26:52 +08:00
这个问题类似于获取分类前 N 条记录,你这里的 user 就是类,可以去查一查。

如果你要具体的优化语句,可以把表的代码复制出来,我比较懒,懒得去新建一个
levelworm
2020-04-23 11:27:29 +08:00
不能用窗口函数吗?不能的话这个不知道行不行

select
*
from (
select
*
from
order
order by
user_id, time asc
) as x
group by cid
Nostalgiaaaa
2020-04-23 11:27:52 +08:00
试一下 partition by,解决这类首单,首次,最后一次的问题
简单搜了一下应该是一个类似的问题
https://stackoverflow.com/questions/18987727/sql-query-using-partition-by

SELECT *
FROM
(SELECT * ,
ROW_NUMBER() over( partition by user_id
ORDER BY create_time DESC ) AS rank
FROM order
WHERE order_status IN ( 'PRE_DELIVER', 'PRE_ACCEPT', 'AFTER_DELIVER' )
AND user_id IN (1,2,3,4)
AND deleted = 0 )
WHERE rank = 1

另外,分析型 sql 建议做成定时任务定时刷新,比如半小时一次,实时查意义不大并且性能问题很严重
levelworm
2020-04-23 11:30:08 +08:00
@Nostalgiaaaa 他这个估计版本比较老用不了窗口函数,我猜测
iffi
2020-04-23 11:45:15 +08:00
可用 join
liubx
2020-04-23 11:45:20 +08:00
@mwiker 感谢,之前没了解窗口函数,刚看了下。窗口函数确实可以解决
liubx
2020-04-23 11:46:41 +08:00
@Nostalgiaaaa 嗯,谢谢回复。现在决定做成定时任务了
icchux
2020-04-23 11:47:02 +08:00
@levelworm 这个可以 我上午刚用这个子查询的方法 统计一些东西 但这个是慢查询 数据量大的时候特别慢。。。。。。mysql 低版本对于这种统计要求真的烦心
liubx
2020-04-23 11:48:20 +08:00
@levelworm 嗯,窗口函数可以解决。但是涉及多张表了。还是决定重新建张表存储了。
liubx
2020-04-23 11:49:49 +08:00
@icchux 可以用定时任务,把统计结果存到另一张表里。
icchux
2020-04-23 11:53:26 +08:00
@iffi 大佬可否指点一二
levelworm
2020-04-23 11:54:44 +08:00
@icchux 没有窗口函数真的要死了,我现在随便一个查询都有几个窗口函数
ooyy
2020-04-23 12:01:07 +08:00
sql 查询改动小,性能要看表数据量
with t as (
select *, ROW_NUMBER() over (partition by user_id ORDER BY create_time DESC ) AS rn
from order inner join c_order on order.id = c_order.id ...
) select * from t where rn = 1 and a.order_status IN ( 'PRE_DELIVER', 'PRE_ACCEPT', 'AFTER_DELIVER' )
and ...
seanseek
2020-04-23 13:09:54 +08:00
能不能按照 id 和时间排序,然后再去个重?
jeff0819
2020-04-23 15:11:18 +08:00
建议中间表,写个脚本跑出来再去查
seanseek
2020-04-23 16:37:15 +08:00
group by user_id 可以

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/665228

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX