目录
一、力扣原题链接
二、题目描述
三、建表语句
四、题目分析
五、SQL解答
六、最终答案
七、验证
八、知识点
一、力扣原题链接
1843. 可疑银行账户
二、题目描述
表:
Accounts
+----------------+------+ | Column Name | Type | +----------------+------+ | account_id | int | | max_income | int | +----------------+------+ account_id 是这张表具有唯一值的列。 每行包含一个银行账户每月最大收入的信息。表:
Transactions
+----------------+----------+ | Column Name | Type | +----------------+----------+ | transaction_id | int | | account_id | int | | type | ENUM | | amount | int | | day | datetime | +----------------+----------+ transaction_id 是这张表具有唯一值的列。 每行包含一条转账信息。 type 是枚举类型(包含'Creditor','Debtor'),其中 'Creditor' 表示用户向其账户存入资金,'Debtor' 表示用户从其账户取出资金。 amount 是交易过程中的存入/取出的金额。如果一个账户在 连续两个及以上 月份的 总收入 超过最大收入(
max_income
),那么认为这个账户 可疑。 账户当月 总收入 是当月存入资金总数(即 transactions 表中 type 字段的'Creditor'
)。编写一个解决方案,报告所有的 可疑 账户。
以 任意顺序 返回结果表
返回结果格式如下示例所示。
示例 1:
输入: Accounts 表: +------------+------------+ | account_id | max_income | +------------+------------+ | 3 | 21000 | | 4 | 10400 | +------------+------------+ Transactions 表: +----------------+------------+----------+--------+---------------------+ | transaction_id | account_id | type | amount | day | +----------------+------------+----------+--------+---------------------+ | 2 | 3 | Creditor | 107100 | 2021-06-02 11:38:14 | | 4 | 4 | Creditor | 10400 | 2021-06-20 12:39:18 | | 11 | 4 | Debtor | 58800 | 2021-07-23 12:41:55 | | 1 | 4 | Creditor | 49300 | 2021-05-03 16:11:04 | | 15 | 3 | Debtor | 75500 | 2021-05-23 14:40:20 | | 10 | 3 | Creditor | 102100 | 2021-06-15 10:37:16 | | 14 | 4 | Creditor | 56300 | 2021-07-21 12:12:25 | | 19 | 4 | Debtor | 101100 | 2021-05-09 15:21:49 | | 8 | 3 | Creditor | 64900 | 2021-07-26 15:09:56 | | 7 | 3 | Creditor | 90900 | 2021-06-14 11:23:07 | +----------------+------------+----------+--------+---------------------+ 输出: +------------+ | account_id | +------------+ | 3 | +------------+ 解释: 对于账户 3: - 在 2021年6月,用户收入为 107100 + 102100 + 90900 = 300100。 - 在 2021年7月,用户收入为 64900。 可见收入连续两月超过21000的最大收入,因此账户3列入结果表中。对于账户 4: - 在 2021年5月,用户收入为 49300。 - 在 2021年6月,用户收入为 10400。 - 在 2021年7月,用户收入为 56300。 可见收入在5月与7月超过了最大收入,但6月没有。因为账户没有没有连续两月超过最大收入,账户4不列入结果表中。
三、建表语句
drop table if exists Accounts;
drop table if exists Transactions;
Create table If Not Exists Accounts (account_id int, max_income int);
Create table If Not Exists Transactions (transaction_id int, account_id int, type ENUM('creditor', 'debtor'), amount int, day datetime);
Truncate table Accounts;
insert into Accounts (account_id, max_income) values ('3', '21000');
insert into Accounts (account_id, max_income) values ('4', '10400');
Truncate table Transactions;
insert into Transactions (transaction_id, account_id, type, amount, day) values ('2', '3', 'Creditor', '107100', '2021-06-02 11:38:14');
insert into Transactions (transaction_id, account_id, type, amount, day) values ('4', '4', 'Creditor', '10400', '2021-06-20 12:39:18');
insert into Transactions (transaction_id, account_id, type, amount, day) values ('11', '4', 'Debtor', '58800', '2021-07-23 12:41:55');
insert into Transactions (transaction_id, account_id, type, amount, day) values ('1', '4', 'Creditor', '49300', '2021-05-03 16:11:04');
insert into Transactions (transaction_id, account_id, type, amount, day) values ('15', '3', 'Debtor', '75500', '2021-05-23 14:40:20');
insert into Transactions (transaction_id, account_id, type, amount, day) values ('10', '3', 'Creditor', '102100', '2021-06-15 10:37:16');
insert into Transactions (transaction_id, account_id, type, amount, day) values ('14', '4', 'Creditor', '56300', '2021-07-21 12:12:25');
insert into Transactions (transaction_id, account_id, type, amount, day) values ('19', '4', 'Debtor', '101100', '2021-05-09 15:21:49');
insert into Transactions (transaction_id, account_id, type, amount, day) values ('8', '3', 'Creditor', '64900', '2021-07-26 15:09:56');
insert into Transactions (transaction_id, account_id, type, amount, day) values ('7', '3', 'Creditor', '90900', '2021-06-14 11:23:07');
四、题目分析
需求:
连续两个及以上 月份的 总收入 超过最大收入(max_income),那么认为这个账户 可疑
解答:
1、要求每月总收入需要先按月统计所有的收入总和
2、筛选每月大于最大收入的用户
3、用等差求连续月
4、筛选连续大于2月的用户
五、SQL解答
with t1 as (selectDATE_FORMAT(day,'%Y-%m') ny,substring(day,1,7) ny1,account_id,-- 1、每月收入总和sum(amount) sum_amount,dense_rank() over (partition by account_id order by DATE_FORMAT(day,'%Y-%m')) drfrom transactions twhere type = 'Creditor'group by ny,ny1,account_id-- 2、筛选每月大于最大收入having sum_amount > (select max_income from accounts where account_id = t.account_id)
),t2 as (
selectaccount_id,-- 3、日期等差求连续date_add(str_to_date(concat(ny,'-01'),'%Y-%m-%d'),interval -dr month) as day2
from t1
group by day2,account_id
-- 4、最少连续2天
having count(date_add(str_to_date(concat(ny,'-01'),'%Y-%m-%d'),interval -dr month)) >= 2
)
select distinct account_id from t2
;
六、最终答案
with t1 as (selectDATE_FORMAT(day,'%Y-%m') ny,substring(day,1,7) ny1,account_id,-- 1、每月收入总和sum(amount) sum_amount,dense_rank() over (partition by account_id order by DATE_FORMAT(day,'%Y-%m')) drfrom transactions twhere type = 'Creditor'group by ny,ny1,account_id-- 2、筛选每月大于最大收入having sum_amount > (select max_income from accounts where account_id = t.account_id)
),t2 as (
selectaccount_id,-- 3、日期等差求连续date_add(str_to_date(concat(ny,'-01'),'%Y-%m-%d'),interval -dr month) as day2
from t1
group by day2,account_id
-- 4、最少连续2天
having count(date_add(str_to_date(concat(ny,'-01'),'%Y-%m-%d'),interval -dr month)) >= 2
)
select distinct account_id from t2
;