我们公司对不忠的员工是零容忍。老大说了:看到谁在招聘网站上活跃了,第一时间告诉他,立马换人
离谱,遇到员工看新机会,不反思自己的管理问题,就不想想,人家到底为啥看机会
一边盯着谁在招聘网站上活跃,一边让招聘部随时补位,这公司味儿就已经不对了。人还没走,先按贼防;岗位问题、管理问题、薪资问题一个不碰,就盯着简历挂没挂出去,这种管理,省事是省事,烂得也快。
更扎心的是,90%的人都想走,说明问题根本不在“谁不忠”,而在公司自己早就失去留人的能力了。员工把招聘软件当体检,老板把招聘软件当监控,招聘部夹在中间天天找人、天天补洞,最后最先累死的,往往不是要走的人,是还在硬撑的人。
这种公司,嘴上喊零容忍,实际是对现实零判断。
算法题:超过 5 名学生的课
这题一上来就别想着 count(*) 一把梭。真在线上写 SQL,我第一眼先防的不是查不出来,是重复数据把你坑了。
题目是“超过 5 名学生的课”,翻成人话就是:哪门课被选的人数,大于 5。
这种题不难,难的是很多人写得太顺手,结果把边界写丢了。比如一门课里同一个学生有重复选课记录,或者中间表脏数据没清干净,你那个 count(*) 一跑,答案看着对,其实已经偏了。
先说最直接的写法。假设有一张选课表 course_student,字段就两个:
course_idstudent_id
那 Java 里拼出来的 SQL,大概会这么写:
String sql = """
select course_id
from course_student
group by course_id
having count(distinct student_id) > 5
""";
这里我故意用了 count(distinct student_id),不是 count(*)。
因为这类题,默认脑子里要先过一遍数据质量。只要你不能 100% 保证 (course_id, student_id) 唯一,distinct 基本就别省。面试里省这一下,可能不扣分。线上你省这一下,报表就开始飘。
如果题目还要求把课程名也查出来,那一般会再连一张课程表:
String sql = """
select c.course_id, c.course_name
from course c
join (
select course_id
from course_student
group by course_id
having count(distinct student_id) > 5
) t on c.course_id = t.course_id
""";
这个写法比上来就三表乱 join 要干净。先把“超过 5 人的课”这个结果集收缩出来,再去拿课程信息,思路顺一点,执行计划也更容易看。
如果你非要用 Java 集合做一遍,其实也能做。比如笔试题不给你数据库,就给一个选课列表,那就老老实实统计:
import java.util.*;
publicclassMain{
publicstatic List<String> findHotCourses(List<String[]> records){
Map<String, Set<String>> courseMap = new HashMap<>();
for (String[] record : records) {
String studentId = record[0];
String courseId = record[1];
courseMap
.computeIfAbsent(courseId, k -> new HashSet<>())
.add(studentId);
}
List<String> result = new ArrayList<>();
for (Map.Entry<String, Set<String>> entry : courseMap.entrySet()) {
if (entry.getValue().size() > 5) {
result.add(entry.getKey());
}
}
return result;
}
}
这里也不是随便用 Map<String, Integer> 计数,而是 Map<String, Set<String>>。
原因还是那个老问题:去重。
很多人写成这样:
countMap.put(courseId, countMap.getOrDefault(courseId, 0) + 1);
表面没毛病。只要一门课里同一个学生出现两次,结果就脏了。这种代码在刷题网站可能能过,在真实业务里我一般不太信。
再往前一步,这题其实考的就是两个点:
第一,能不能想到 group by + having。 第二,会不会在计数时顺手把重复学生这个坑补上。
所以标准 SQL 可以记成这样:
select course_id
from course_student
groupby course_id
havingcount(distinct student_id) > 5;
要是题目明确说了选课记录天然不重复,那你再换成 count(*) 也行。但这话必须题目说,不是你自己脑补。
很多算法题写到最后,容易写成教科书答案。可这类题我更看重一个习惯:你是不是先怀疑数据,再下手写统计。
因为统计类题最烦的不是不会写,是你写出来看着特别像对的,结果线上一对账,差了几百条,还不好排查。
这题就这么大点东西,核心不在语法,在手感。计数之前,先想想该不该去重。这个顺序对了,后面一般就不会太离谱。