SQL架构
表: Visits
+---------------+---------+ | Column Name | Type | +---------------+---------+ | user_id | int | | visit_date | date | +---------------+---------+ (user_id, visit_date) 是该表的主键 该表的每行表示 user_id 在 visit_date 访问了银行
表: Transactions
+------------------+---------+ | Column Name | Type | +------------------+---------+ | user_id | int | | transaction_date | date | | amount | int | +------------------+---------+ 该表没有主键,所以可能有重复行 该表的每一行表示 user_id 在 transaction_date 完成了一笔 amount 数额的交易 可以保证用户 (user) 在 transaction_date 访问了银行 (也就是说 Visits 表包含 (user_id, transaction_date) 行)
银行想要得到银行客户在一次访问时的交易次数和相应的在一次访问时该交易次数的客户数量的图表
写一条 SQL 查询多少客户访问了银行但没有进行任何交易,多少客户访问了银行进行了一次交易等等
结果包含两列:
transactions_count:
客户在一次访问中的交易次数visits_count:
在transactions_count
交易次数下相应的一次访问时的客户数量
transactions_count
的值从 0
到所有用户一次访问中的 max(transactions_count)
按 transactions_count
排序
下面是查询结果格式的例子:
Visits
表: +---------+------------+ | user_id | visit_date | +---------+------------+ | 1 | 2020-01-01 | | 2 | 2020-01-02 | | 12 | 2020-01-01 | | 19 | 2020-01-03 | | 1 | 2020-01-02 | | 2 | 2020-01-03 | | 1 | 2020-01-04 | | 7 | 2020-01-11 | | 9 | 2020-01-25 | | 8 | 2020-01-28 | +---------+------------+Transactions
表: +---------+------------------+--------+ | user_id | transaction_date | amount | +---------+------------------+--------+ | 1 | 2020-01-02 | 120 | | 2 | 2020-01-03 | 22 | | 7 | 2020-01-11 | 232 | | 1 | 2020-01-04 | 7 | | 9 | 2020-01-25 | 33 | | 9 | 2020-01-25 | 66 | | 8 | 2020-01-28 | 1 | | 9 | 2020-01-25 | 99 | +---------+------------------+--------+ 结果表: +--------------------+--------------+ |transactions_count
| visits_count | +--------------------+--------------+ | 0 | 4 | | 1 | 5 | | 2 | 0 | | 3 | 1 | +--------------------+--------------+ * 对于 transactions_count = 0, visits 中 (1, "2020-01-01"), (2, "2020-01-02"), (12, "2020-01-01") 和 (19, "2020-01-03") 没有进行交易,所以 visits_count = 4 。 * 对于 transactions_count = 1, visits 中 (2, "2020-01-03"), (7, "2020-01-11"), (8, "2020-01-28"), (1, "2020-01-02") 和 (1, "2020-01-04") 进行了一次交易,所以 visits_count = 5 。 * 对于 transactions_count = 2, 没有客户访问银行进行了两次交易,所以 visits_count = 0 。 * 对于 transactions_count = 3, visits 中 (9, "2020-01-25") 进行了三次交易,所以 visits_count = 1 。 * 对于 transactions_count >= 4, 没有客户访问银行进行了超过3次交易,所以我们停止在 transactions_count = 3 。 如下是这个例子的图表:
with recursive t as( # 用递归 显示 0到 3(由子查询找到 transactions_count 的 最大值)数字
select (select ifnull(max(ca),0) from (select # ifnull 保证 无最大值时 置零 (也就是说当transactions_count 没有大于零的值时)
s1.ca,count(user_id)
from
(
select
count(amount) ca,user_id
from
Transactions
group by
user_id,Transaction_date
) s1
group by
s1.ca) s2) as n # 初始语句(非递归部分)
union all
select n-1 from t where n>0 # 递归部分语句 注意一定要大于零 这样才能保证 最小值为 0 否则 为-1
)
select t.n transactions_count,ifnull(ssss1.visits_count,0) visits_count from t left join (
select
0 transactions_count,count(user_id) visits_count # 选出 transactions_count = 0 的客户数量(啥也没有时 输出也是 0,0)
from
Visits
where (user_id,visit_date) not in (select user_id,Transaction_date from Transactions)
union all
select
s1.ca transactions_count,count(user_id) visits_count #选出 transactions_count != 0 的客户数量
from
(
select
count(amount) ca,user_id
from
Transactions
group by
user_id,Transaction_date
) s1
group by
s1.ca
) ssss1
on t.n = ssss1.transactions_count
order by transactions_count
笔记:
MYSQL WITH recursive使用
由于在项目中有使用到recursive,因此在此做记录
语法
WITH recursive 表名 AS (
初始语句(非递归部分)
UNION ALL
递归部分语句
)
[ SELECT| INSERT | UPDATE | DELETE]
1
2
3
4
5
6
用法1:输出1~n或者求 1~n的和
WITH recursive t AS(
SELECT 1 AS n
UNION ALL
SELECT n+1 FROM t WHERE n<10
)
SELECT * FROM t
SELECT SUM(n) FROM t;
————————————————
版权声明:本文为CSDN博主「dapeng chen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sin_dapeng/article/details/121673632