发布时间:2026/7/25 5:15:05
请写一个SQL查询,目标:从employees表中查询每个部门工资排名前3的员工。表结构:employees(id, name, department, salary, hire_date)要求:1. 如果工资相同,按入职日期升序排列2. 每个部门独立排名3. 返回部门、姓名、工资、入职日期、排名AI立刻给出了一个使用窗口函数的答案。但问题来了——老张不懂窗口函数。所以我的策略是:先用AI生成正确代码,再用AI逐行解释,最后让AI把SQL逻辑翻译成Python代码,这样老张就能理解原理了。## 第一步:AI生成SQL核心代码以下是AI生成的SQL查询代码(我加了注释):sql-- 使用窗口函数ROW_NUMBER()为每个部门内的员工按工资降序编号-- 如果工资相同,则按入职日期升序(越早入职排名越前)WITH ranked_employees AS ( SELECT department, name, salary, hire_date, ROW_NUMBER() OVER ( PARTITION BY department ORDER BY salary DESC, hire_date ASC ) AS rank_num FROM employees)-- 只保留排名前3的员工SELECT department, name, salary, hire_date, rank_numFROM ranked_employeesWHERE rank_num <= 3ORDER BY department, rank_num;这段代码的核心是ROW_NUMBER()窗口函数。PARTITION BY department表示按部门分组,ORDER BY salary DESC, hire_date ASC表示组内先按工资降序排,工资相同再按入职日期升序排。最后用rank_num <= 3筛选出前三名。## 第二步:AI把SQL翻译成Python(老张能理解)为了让老张理解逻辑,我让AI生成等价的Python代码:python# 模拟SQL窗口函数的Python实现# 对每个部门内的员工排序,选出前三名def get_top3_per_department(employees): """ employees: list of dicts,每个元素如{'name':'张三', 'department':'技术部', 'salary':20000, 'hire_date':'2020-01-01'} 返回:每个部门工资前3的员工列表(按部门分组,组内按工资降序、日期升序) """ from collections import defaultdict import operator # 第一步:按部门分组(类似SQL的PARTITION BY) departments = defaultdict(list) for emp in employees: departments[emp['department']].append(emp) result = [] # 第二步:对每个部门的员工排序(类似ORDER BY) for dept, emp_list in departments.items(): # 按工资降序排,工资相同按入职日期升序排 sorted_emps = sorted( emp_list, key=lambda e: (-e['salary'], e['hire_date']) # 负号表示降序 ) # 第三步:取前3名(类似ROW_NUMBER() + WHERE rank <= 3) top3 = sorted_emps[:3] # 添加排名信息 for rank, emp in enumerate(top3, start=1): emp['rank'] = rank result.append(emp) # 按部门、排名排序输出 result.sort(key=lambda e: (e['department'], e['rank'])) return result# 测试数据test_data = [ {'name': '张三', 'department': '技术部', 'salary': 20000, 'hire_date': '2020-01-01'}, {'name': '李四', 'department': '技术部', 'salary': 18000, 'hire_date': '2021-03-15'}, {'name': '王五', 'department': '技术部', 'salary': 20000, 'hire_date': '2019-06-01'}, {'name': '赵六', 'department': '市场部', 'salary': 15000, 'hire_date': '2022-02-10'}, {'name': '钱七', 'department': '市场部', 'salary': 16000, 'hire_date': '2021-11-20'},]top_employees = get_top3_per_department(test_data)for emp in top_employees: print(f"{emp['department']} - {emp['name']} - 工资:{emp['salary']} - 入职日期:{emp['hire_date']} - 排名:{emp['rank']}")运行这段代码,输出结果是:技术部 - 王五 - 工资:20000 - 入职日期:2019-06-01 - 排名:1技术部 - 张三 - 工资:20000 - 入职日期:2020-01-01 - 排名:2技术部 - 李四 - 工资:18000 - 入职日期:2021-03-15 - 排名:3市场部 - 钱七 - 工资:16000 - 入职日期:2021-11-20 - 排名:1市场部 - 赵六 - 工资:15000 - 入职日期:2022-02-10 - 排名:2老张看到这个结果恍然大悟:“原来就是先分组,再排序,最后取前三个!” 他之前用暴力循环写得很复杂,而AI给出的方案把问题分解成了三个清晰的步骤。## 第三步:AI教我优化和扩展我又追问AI:“如果工资相同,不想用入职日期区分,而是希望并列排名(比如两个20000的都是第一名,下一个是第三名),该怎么做?”AI很快给出了使用DENSE_RANK的变体:sql-- 使用DENSE_RANK实现并列排名WITH ranked_employees AS ( SELECT department, name, salary, hire_date, DENSE_RANK() OVER ( PARTITION BY department ORDER BY salary DESC ) AS rank_num FROM employees)SELECT * FROM ranked_employees WHERE rank_num <= 3;然后AI解释:DENSE_RANK和ROW_NUMBER的区别是,DENSE_RANK会跳过重复的序号,但不会跳过序号。比如工资20000有两个人,他们并列第一(rank=1),下一个工资18000的人就是第二(rank=2),而不是第三。老张说:“这个太实用了!面试官可能还会问并列情况。”## 第四步:用AI生成面试模拟题为了让老张彻底掌握,我让AI生成了一道类似的面试题,并附上解答:题目:有一个销售表sales(salesperson, product, amount, sale_date),查询每个销售员销售额最高的前2个产品(按金额降序,金额相同按销售日期升序)。解答思路:1. 使用ROW_NUMBER() OVER (PARTITION BY salesperson ORDER BY amount DESC, sale_date ASC)2. 筛选行号<=2的记录老张试着用AI生成的Python代码自己改了一次,终于理解了窗口函数的本质——“就是在分组内做排序和编号”。## 总结花了一晚上时间,我用AI Coding帮一个前端同事解决了SQL跳槽面试题。整个过程让我深刻感受到:AI工具最大的价值不是替代程序员,而是帮助我们在不熟悉的领域快速学习和验证。具体来说,这次经历给了我三个启发:1.AI是“翻译器”:把SQL逻辑翻译成Python这种同事熟悉的语言,降低了理解门槛。2.AI是“加速器”:以前查文档、调试SQL可能要半小时,现在AI几秒钟给出正确代码,还能自动生成测试数据。3.AI是“面试教练”:可以模拟出各种变体题目,帮助系统掌握知识点。当然,AI生成的代码不一定完美,比如上面Python代码里我没有处理空部门的情况(这是故意留的坑,让老张自己发现)。但关键在于:有了AI,我们不再需要记住所有细节,而是学会如何提问、如何验证、如何把AI的输出改造成适合自己场景的代码。最终,老张顺利通过了面试,在第二家公司拿到了Offer。他请我吃饭时说:“以后遇到不懂的,我就用AI先写个Python版本理解,再翻译成SQL。” 这大概就是AI时代程序员的正确打开方式吧——不惧怕陌生领域,因为AI就是我们随时随地的技术合伙人。