第五版_完整

This commit is contained in:
jianqi
2026-09-14 16:39:48 +08:00
parent c2909191d2
commit e8be87eca0
5 changed files with 147 additions and 53 deletions
+49 -19
View File
@@ -20,7 +20,9 @@ class StatisticsDao:
@staticmethod
def get_class_gender_distribution(db: Session) -> List[ClassGenderDistributionItem]:
"""
**多维度班级统计**:统计每个班级的总人数,以及按性别(男、女)细分的人数分布。
"""
all_cls_gender_stats = (
db.query(
StuInfo.cls_id.label("cls_id"),
@@ -38,12 +40,16 @@ class StatisticsDao:
total_cnt=i.total_cnt,
man_cnt=i.man_cnt,
female_cnt=i.female_cnt,
) for i in all_cls_gender_stats
)
for i in all_cls_gender_stats
]
# 查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩。
@staticmethod
def get_stu_info_all_exams_above_score(db: Session, score: float) -> List[StuInfoAllExamAboveScore]:
"""
# 查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩 -- 参数: 分数
"""
stu_id_list_query = (
db.query(StuScore.stu_id)
.filter(StuScore.is_deleted == 0)
@@ -87,7 +93,11 @@ class StatisticsDao:
@staticmethod
def get_stu_dict_who_fail(db: Session) -> Dict[str, List[StuScore]]:
"""
获取不及格的学生信息 {stu_id, [StuScore]}
"""
stu_fail_dict = defaultdict(list)
data = (db.query(StuScore)
.options(joinedload(StuScore.student)) # 预加载模式: 让 SQLAlchemy 在第一次查成绩表时,通过 JOIN 语句一次性把学生信息查出来。
.filter(and_(StuScore.is_deleted == 0, StuScore.exam_score <= 60))
@@ -98,7 +108,14 @@ class StatisticsDao:
@staticmethod
def find_students_fail_count(db: Session, fail_cnt: int) -> List[FailingStudentItem]:
test_max_cnt = len(db.query(StuScore.exam_attempt).group_by(StuScore.exam_attempt).all())
"""
# 2、查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细 -- 参数: 不及格次数
"""
test_max_cnt = len(db.query(StuScore.exam_attempt)
.filter(StuScore.is_deleted == 0)
.group_by(StuScore.exam_attempt)
.all()
)
if fail_cnt > test_max_cnt:
raise HTTPException(status_code = 400, detail = f'最大次数为{test_max_cnt}')
@@ -131,9 +148,12 @@ class StatisticsDao:
# 统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序。
@staticmethod
def find_class_exam_averages(db: Session, order_choose: int) -> List[ClassExamAvgScoreItem]:
"""
# 统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序 -- 参数: 1:低到高, 2:高到低
"""
avg_score = func.avg(StuScore.exam_score)
order_score = asc(avg_score) if order_choose == 1 else desc(avg_score)
aaa = (db.query(
finally_data = (db.query(
StuInfo.cls_id,
StuScore.exam_attempt,
func.avg(StuScore.exam_score).label("avg_score"),
@@ -146,7 +166,7 @@ class StatisticsDao:
# 班级 - 考试场次 - 平均分
ans = []
for row in aaa:
for row in finally_data:
ans.append(
ClassExamAvgScoreItem(
exam_attempt=row.exam_attempt,
@@ -160,17 +180,20 @@ class StatisticsDao:
@staticmethod
def find_top_salary_students(db: Session, top_n: int) -> List[TopSalaryStudentItem]:
aaa = (db.query(
"""
# 1、统计就业薪资排名 Top N(动态输入 N)的学生的姓名、班级、就业时间和就业公司。 -- 参数: top_N
"""
finally_data = (db.query(
StudentEmployManage.send_offer_time,
StudentEmployManage.emp_company,
StudentEmployManage.salary,
StuInfo.name,
StuInfo.cls_id
).join(StuInfo, StuInfo.id == StudentEmployManage.stu_id)
.filter(StudentEmployManage.is_deleted == 0, StudentEmployManage.is_deleted == 0)
.order_by(StudentEmployManage.salary.desc())
.limit(top_n)
)
.filter(StudentEmployManage.is_deleted == 0, StudentEmployManage.is_deleted == 0)
.order_by(StudentEmployManage.salary.desc())
.limit(top_n)
)
ans = [
TopSalaryStudentItem(
@@ -180,26 +203,30 @@ class StatisticsDao:
emp_company_name=row.emp_company,
salary=row.salary
)
for row in aaa
for row in finally_data
]
return ans
@staticmethod
def find_students_employment_duration(db: Session) -> List[StudentEmpDurationItem]:
"""
# 2、统计每个学生的就业时长(计算公式:offer下发时间 - 就业开放时间) -- 参数: 无
"""
time = func.datediff(StudentEmployManage.send_offer_time, StudentEmployManage.emp_open_time)
aaa = (db.query(
finally_data = (db.query(
StuInfo.id,
StuInfo.cls_id,
StuInfo.name,
time.label("time")
).join(StudentEmployManage, StuInfo.id == StudentEmployManage.stu_id)
.filter(StuInfo.is_deleted == 0,
StuInfo.is_deleted == 0,
StudentEmployManage.send_offer_time.isnot(None),
StudentEmployManage.emp_open_time.isnot(None))
.order_by(time).all()
)
.filter(StuInfo.is_deleted == 0,
StudentEmployManage.is_deleted == 0,
StudentEmployManage.send_offer_time.isnot(None),
StudentEmployManage.emp_open_time.isnot(None))
.order_by(time).all()
)
ans = [
StudentEmpDurationItem(
@@ -208,13 +235,16 @@ class StatisticsDao:
cls_id=row.cls_id,
offer_time=row.time
)
for row in aaa
for row in finally_data
]
return ans
@staticmethod
def find_class_avg_employment_duration(db: Session) -> List[ClassAvgEmpDurationItem]:
"""
# 3、统计每个班级的平均就业时长(仅统计进入就业阶段,即有就业开放时间的学生) -- 参数: 无<br>
"""
duration_time = func.datediff(StudentEmployManage.send_offer_time, StudentEmployManage.emp_open_time)
class_avg_query = (db.query(
StuInfo.cls_id,