题目描述
(通过次数2,270 | 提交次数5,029,通过率45.14%)
表: 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 是转账的存取金额。 写一个SQL查询语句列示所有的可疑账户。 如果一个账户在连续两个及以上月份中总收入超过最大收入(max_income),那么这个账户可疑。账户当月总收入是当月存入资金总数(即transactions 表中type字段的'Creditor')。 返回的结果表以transaction_id排序。 查询结果格式如下。 示例 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不列入结果表中。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/suspicious-bank-accounts
//测试数据 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); insert into Accounts (account_id, max_income) values ('3', '21000'); insert into Accounts (account_id, max_income) values ('4', '10400'); 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');
解题思路
Accounts表保存了所有的账户以及账户合法的最大月收入。
Transactions表保存了账户的资金存入取出记录。如果某个账户,月累计存入资金超过了该账户合法的最大月收入,则该账户为非正常收入账户。如果一个账户连续2个月或以上都为非正常收入账户,则该账户可疑。
那么,可以按如下步骤实现题目的要求:
第一步:统计每个账户每个月的累计存入资金;
使用GROUP BY+SUM即可实现。
第二步:筛选出每个月的非正常收入账户;
可以直接和Accounts表关联,筛选出月累计存入资金超过了该账户合法的最大月收入的记录。
第三步:筛选出连续2个月或以上的非正常收入账户;
连续N次满足某个条件的场景,可以参考推文《单挑力扣(LeetCode)SQL笔试题:1454. 活跃用户(难度:困难)》。
本题目仅要求查询连续2个月,可以使用INNER JOIN自关联的方式,将当月与上月的数据关联到一行。如果能关联上,则表示当月与上月都是非正常收入账户。
当然,返回时需要考虑重复账户,使用DISTINCT关键字去重即可。
参考SQL
未特别说明的情况下,参考SQL为基于MySQL8.0实现。
with tmp1 as ( select date_format(day,'%Y-%m-01') mon, account_id, sum(amount) amount from Transactions where type = 'Creditor' group by date_format(day,'%Y-%m-01'), account_id ), tmp2 as ( select a.mon, a.account_id from tmp1 a inner join Accounts b on a.account_id = b.account_id and a.amount > b.max_income ) select distinct a.account_id from tmp2 a inner join tmp2 b on date_sub(a.mon, interval 1 month)=b.mon and a.account_id = b.account_id;
本站所有内容均为原创,本站保留所有权利。仅允许非商业用途的转载,但必须注明来源网站、作者、来源链接!否则,由此造成的一切后果,由转载方承担!
干货分享、技术提升、面试笔试、学习交流,欢迎关注公众号:xuesql。QQ学习交流群:209942678。