查询一天内登陆两次以上的用户
分析:
- 数据存储结构为:用户信息表 和 登陆记录表。
登陆记录表一般会有用户ID,登陆时间这两个核心字段。 - 先从登陆信息表中找到一天内登陆两次以上的用户(id)
- 关联用户信息表得到用户信息。
实现
创建用户表(user_info)
create tableuser_info
(
id
bigint unsigned AUTO_INCREMENT,
username
varchar(50) NOT NULL,
password
varchar(50) NOT NULL,
gender
ENUM(‘male’, ‘female’),
birthday
DATETIME NOT NULL,
phone_number
varchar(20) NOT NULL,
email
varchar(100),
create_time
DATETIME NOT NULL,
PRIMARY KEY(id
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创建登陆记录表(login)
create table login
(
id
bigint unsigned AUTO_INCREMENT,
user_id
bigint unsigned NOT NULL,
login_time
DATETIME NOT NULL,
PRIMARY KEY(id
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
代码
SELECT a.user_id, user_info.username, user_info.gender
FROM (
SELECT user_id, count(login_time) AS cnt
FROM login
WHERE login_time >= ‘2024-04-01 00:00:00’ AND login_time <= ‘2024-04-01 23:59:59’
GROUP BY user_id
HAVING cnt >=0
) a
LEFT JOIN user_info
ON user_info.id = a.user_id
销量前10的品类和商品
分析
- 数据存储结构: 订单明细表
- 先计算每个品类/商品的销量
- 对每个品类/商品按照销量倒排序
- 取销量前10的品类/商品的结果
实现
CREATE TABLEorder_item
(
order_id
varchar(50) DEFAULT NULL COMMENT ‘订单ID’,
goods_id
int(11) NOT NULL COMMENT ‘商品ID’,
shop_id
varchar(20) NOT NULL COMMENT ‘门店ID’,
cate_id
int(11) DEFAULT NULL COMMENT ‘商品品类ID’,
price
decimal(12,2) DEFAULT NULL COMMENT ‘商品销售单价’,
qty
int DEFAULT NULL COMMENT ‘商品销售数量’,
sale_value
decimal(18,3) DEFAULT NULL COMMENT ‘商品销售额=商品销售单价 * 销售量’,
ori_sale_value
decimal(18,3) DEFAULT NULL COMMENT ‘商品原价’,
sale_date
date NOT NULL COMMENT ‘订单支付日期’,
KEYorder_item_order_id_idx
(order_id
,goods_id
,shop_id
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
代码
SELECT cate_id, sum(sale_value)
FROM order_item
GROUP BY cate_id
ORDER BY sum(sale_value) DESC
LIMIT 10
SELECT
goods_id, sum(sale_value)
FROM order_item
WHERE sale_date >= ‘2023-01-01’ AND sale_date <= ‘2023-01-31’
GROUP BY goods_id
ORDER BY sum(sale_value) DESC
LIMIT 10
统计用户在本店二次购买商品的比例
分析
- 数据存储结构
一般会有一张订单表存储:订单ID, 用户ID,商品ID,购买时间等信息。 - 统计每个用户在店铺的购买次数
- 查询购买一次以上和二次以上的用户数
根据第二步可以计算出每个购买次数的用户数,最终就可以得出购买二次以上的用户比例。
实现
CREATE TABLEorder_list
(
order_id
varchar(50) DEFAULT NULL,
shop_id
varchar(10) NOT NULL COMMENT ‘门店ID’,
pay_time
datetime DEFAULT NULL COMMENT ‘订单支付时间’,
casher_id
varchar(2) COMMENT ‘银员ID’,
cash_value
decimal(28,3) DEFAULT NULL COMMENT ‘订单实收金额=对应订单明细表中SaleValue累加’,
pay_value
decimal(18,2) DEFAULT NULL COMMENT ‘付款金额,pay_value - cash_value = 找零金额’,
discount_value
decimal(18,2) DEFAULT NULL COMMENT ‘订单折扣金额’,
member_id
varchar(50) DEFAULT NULL COMMENT ‘用户ID’,
UNIQUE KEYorder_list_order_id_idx
(order_id
) USING BTREE
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
代码
SELECT
sum(IF(buy_cnt > 1, num, 0)), //购买次数大于1次以上的用户数
sum(num), //所有购买次数的用户数
sum(IF(buy_cnt > 1, num, 0)) / sum(num) //二次购买比例
from (
select buy_cnt, count(member_id) as num
from (
select member_id, count(DISTINCT order_id) as buy_cnt
from order_list
group by member_id;
)a
group by buy_cnt
) b;
提取某月的日活动人数
分析
- 数据存储结构:对于用户在App上的活跃情况,我们一般是采用埋点的方式记录用户在App的操作行为,也就是用户在App上每个操作我们都可以记录这次行为的时间,行为,设备,用户等等一系列的信息。那我们一般会把这些内容存在日志表里,核心字段包括用户ID, 时间,行为内容。
实现
SELECT count(DISTINCT user_id)
FROM login
WHERE login_time >= ‘2024-03-01 00:00:00’ AND login_time <= ‘2024-03-31 23:59:59’
如何求某个商品的最后点击时间
分析
1. 数据存储结构-商品点击记录表:包括 用户ID, 商品ID, 点击时间
实现
CREATE TABLE goods_click_records
(
id
bigint unsigned AUTO_INCREMENT,
goods_id
varchar(20) NOT NULL,
user_id
varchar(20),
click_time
datetime NOT NULL,
PRIMARY KEY(id
)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
SELECT goods_id, max(click_time) as last_click_time
FROM goods_click_records
WHERE goods_id='XXXXX'
SQL中数据如何去重
- GROUP BY 是按照指定的规则对数据进行分组,所谓的分组就是将一个数据划分成若干各组,让然后针对若干个组进行数据处理。分组类似先建立索引再查索引,当数据量比较大时,GROUP BY速度要优先于DISTINCT.
- DISTINCET 是一个关键字,常用于SELECT 之后,用于取出去重之后的值。主要是对数据两两进行比较,需要遍历整个表。可以配合聚合函数COUNT 一起使用,GROUP BY不行。
where 和 having的用法区别
都是基于给定的条件筛选出相对应的结果。
where是一个约束声明,是在查询数据库的结果返回之前对查询条件进行约束,即在结果返回之前起到作用。
where条件的执行顺序是在group by之前,因此where子句的作用是对查询结果分组之前,将不符合条件的行去掉,即在分组之前过滤数据。
where条件中不能包含聚合函数,因为where条件的执行顺序大于聚合函数。
having是一个过滤声明,是在查询数据库的结果返回之后进行过滤,即在执行结果返回值后起到作用。
having子句的作用是筛选满足条件的分组,即在分组之后过滤数据,条件中经常包含聚合函数,使用having条件显示特定的组,也可以使用多个分组标准进行分组。having子句的条件一定是select子句中显示的内容。