1907. 按分类统计薪水

💰银行账户工资分类统计题解析(SQL + Pandas)

在数据分析和数据处理的实际工作中,经常会遇到「将连续型变量分类并统计」的问题。本篇文章将结合一道 LeetCode 风格的 SQL 题目,详细解析如何用 SQL 和 Pandas 分别实现工资分类统计任务,并分析两种方法的优劣。


🧩题目描述

你有一个关于银行账户的表 Accounts,包含以下字段:

列名类型
account_idint
incomeint

account_id 是主键,每一行代表一个银行账户的月收入。

你的任务是:

将所有账户按月收入分为三个类别,并统计每类的账户数量。

工资类别定义如下:

  • Low Salary:所有工资 严格低于 $20000
  • Average Salary:工资 在 $20000 到 $50000 之间(含)
  • High Salary:所有工资 严格高于 $50000

❗注意事项:

  • 输出必须包含三个类别,即使某一类的账户数量为 0。
  • 输出顺序不限。

🧠解题分析

这是一个典型的「分组统计」问题,难点主要在于:

  1. 如何根据 income 的值划分类别。
  2. 如何保证所有三类都出现在输出中(即使某类为 0)。
  3. 如何高效、简洁地实现这一逻辑。

我们可以使用 SQL 的 CASE WHENLEFT JOIN 等语法来构造逻辑分组。Pandas 中可以使用 cut() 函数来划分区间,再进行分组汇总。


🛠️解题方法

方法一:使用 SQL 实现(适用于 MySQL)

SELECT
  category,
  COUNT(a.account_id) AS accounts_count
FROM (
  SELECT 'Low Salary' AS category
  UNION ALL
  SELECT 'Average Salary'
  UNION ALL
  SELECT 'High Salary'
) AS categories
LEFT JOIN Accounts a
  ON (category = 'Low Salary' AND income < 20000)
     OR (category = 'Average Salary' AND income BETWEEN 20000 AND 50000)
     OR (category = 'High Salary' AND income > 50000)
GROUP BY category;

✅ 解读:

  • 构造了一个 包含三个工资类别的临时表categories
  • 通过 LEFT JOIN 将账户与对应类别进行匹配。
  • 使用 COUNT() 汇总每个类别的账户数。
  • 即使某个类别中没有匹配项,依然会显示出来,数量为 0
替代写法(MySQL 8.0+,使用 CTE):
WITH categories AS (
  SELECT 'Low Salary' AS category
  UNION ALL
  SELECT 'Average Salary'
  UNION ALL
  SELECT 'High Salary'
)
SELECT
  c.category,
  COUNT(a.account_id) AS accounts_count
FROM categories c
LEFT JOIN Accounts a
  ON (c.category = 'Low Salary' AND income < 20000)
     OR (c.category = 'Average Salary' AND income BETWEEN 20000 AND 50000)
     OR (c.category = 'High Salary' AND income > 50000)
GROUP BY c.category;

方法二:使用 Pandas 实现

如果你在做数据分析而非数据库查询,Pandas 提供了同样优雅的解法:

import pandas as pd

# 假设 accounts 是读取来的 DataFrame
accounts['category'] = pd.cut(
    accounts['income'],
    bins=[-float('inf'), 20000, 50000, float('inf')],
    labels=['Low Salary', 'Average Salary', 'High Salary'],
    right=False  # 区间左闭右开:满足 <20000, [20000, 50000], >50000
)

# 分组统计
result = accounts.groupby('category').size().reindex(
    ['Low Salary', 'Average Salary', 'High Salary'],
    fill_value=0
).reset_index(name='accounts_count')

✅ 解读:

  • pd.cut() 用于对 income 按区间分组。
  • groupby().size() 获取每组数量。
  • 使用 reindex() 确保所有类别都存在,填充缺失类别为 0。

📊示例说明

假设原始表 Accounts 如下:

account_idincome
110000
220000
330000
460000

期望输出:

categoryaccounts_count
Low Salary1
Average Salary2
High Salary1

⚖️方法对比分析

比较维度SQL 方法Pandas 方法
使用场景数据库查询,适用于后端开发或数据工程任务本地数据分析,适用于数据分析/建模阶段
分类方式LEFT JOIN + 条件匹配pd.cut()
划分区间
保证全类输出使用 UNION ALL
构造类别表 + LEFT JOIN
使用 reindex()
明确补齐缺失类别
简洁性相对更冗长更简洁、直观
可扩展性适合在 SQL 管道中集成适合进一步结合可视化、模型训练等任务

🏁结语

本题的核心考点在于「分类映射 + 分组计数 + 保证完整类别输出」。无论是使用 SQL 还是 Pandas,理解背后的逻辑都是最重要的。在实际开发中,选择哪种方法应根据你所处的工作流程、数据规模和任务需求来定。

掌握这种技巧,不仅可以处理工资类问题,也适用于用户分群、商品定价区间分析、成绩等级划分等各种业务场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值