EsaProcessingService.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. using YBEE.EQM.Core;
  2. namespace YBEE.EQM.Application;
  3. /// <summary>
  4. /// 有效分分析处理服务
  5. /// </summary>
  6. public class EsaProcessingService(IRepository<EsaPlan> rep) : IEsaProcessingService, ITransient
  7. {
  8. /// <summary>
  9. /// 分析处理
  10. /// </summary>
  11. /// <param name="esaPlanId"></param>
  12. /// <returns></returns>
  13. public async Task Execute(int esaPlanId)
  14. {
  15. var plan = await rep.DetachedEntities
  16. .Include(t => t.EsaBaseLines).ThenInclude(t => t.EsaBaseLineCourses)
  17. .FirstOrDefaultAsync(t => t.Id == esaPlanId)
  18. ?? throw Oops.Oh(ErrorCode.E2001);
  19. // 更新状态
  20. await rep.SqlNonQueryAsync($"UPDATE esa_plan SET status = {(short)ProcessingStatus.RUNNING} WHERE id = {esaPlanId}");
  21. try
  22. {
  23. foreach (var esaBaseLine in plan.EsaBaseLines)
  24. {
  25. try
  26. {
  27. // 更新状态
  28. await rep.SqlNonQueryAsync($"UPDATE esa_base_line SET status = {(short)ProcessingStatus.RUNNING} WHERE id = {esaBaseLine.Id}");
  29. // 构造分析学科
  30. var courseIds = string.Join(", ", esaBaseLine.EsaBaseLineCourses.OrderBy(t => t.CourseId).Select(t => t.CourseId));
  31. // 构造取数条件
  32. var whereBaseSql = $"WHERE T1.exam_plan_id = {plan.ExamPlanId} AND exam_sample_type = 1 AND T1.grade_id = {esaBaseLine.GradeId} AND T1.score > 0";
  33. var whereSql = $"{whereBaseSql} AND T1.course_id IN ({courseIds})";
  34. // 删除数据
  35. var deleteWhereSql = $"WHERE esa_plan_id = {esaPlanId} AND esa_base_line_id = {esaBaseLine.Id} AND grade_id = {esaBaseLine.GradeId}";
  36. await rep.SqlNonQueryAsync(@$"
  37. DELETE FROM esa_line_total {deleteWhereSql};
  38. DELETE FROM esa_line_course {deleteWhereSql};
  39. DELETE FROM esa_line_course_score {deleteWhereSql};
  40. ");
  41. #region 区级分析
  42. #region 总分上线
  43. // 总分上线分
  44. var totalLineScore = await rep.SqlScalarAsync<decimal>(@$"
  45. SELECT MIN(T1.total_score) AS line_score
  46. FROM
  47. (
  48. SELECT total_score
  49. FROM
  50. (
  51. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  52. FROM exam_score AS T1
  53. {whereSql}
  54. GROUP BY T1.exam_student_id
  55. ) AS T1
  56. ORDER BY T1.total_score DESC
  57. LIMIT {esaBaseLine.LineCount}
  58. ) AS T1;
  59. ");
  60. // 总分上线均分
  61. var totalLineAvgScore = Math.Round(await rep.SqlScalarAsync<decimal>(@$"
  62. SELECT AVG(T1.total_score) AS line_avg_score
  63. FROM
  64. (
  65. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  66. FROM exam_score AS T1
  67. {whereSql}
  68. GROUP BY T1.exam_student_id
  69. ) AS T1
  70. WHERE T1.total_score >= {totalLineScore};
  71. "), 2);
  72. // 更新有效系数
  73. var factor = Math.Round(totalLineScore / totalLineAvgScore, 8);
  74. await rep.SqlNonQueryAsync($"UPDATE esa_base_line SET line_score = {totalLineScore}, factor = {factor} WHERE id = {esaBaseLine.Id}");
  75. // 实际上线人数
  76. var factLineCount = await rep.SqlScalarAsync($@"
  77. SELECT COUNT(1) AS line_count
  78. FROM
  79. (
  80. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  81. FROM exam_score AS T1
  82. {whereSql}
  83. GROUP BY T1.exam_student_id
  84. ) AS T1
  85. WHERE T1.total_score >= {totalLineScore};
  86. ");
  87. // 总均分
  88. var totalAvgScore = Math.Round(await rep.SqlScalarAsync<decimal>(@$"
  89. SELECT AVG(total_score) AS avg_score
  90. FROM
  91. (
  92. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  93. FROM exam_score AS T1
  94. {whereSql}
  95. GROUP BY T1.exam_student_id
  96. ) AS T1;
  97. "), 2);
  98. // 学科有效分
  99. var totalRelativeDiff = Math.Round((totalLineScore - totalAvgScore) / totalLineScore, 8);
  100. await rep.SqlNonQueryAsync(@$"
  101. -- 总分
  102. INSERT INTO esa_line_course_score(esa_level, esa_line_level, esa_plan_id, esa_base_line_id, grade_id, course_id, avg_score, line_avg_score, line_score, relative_diff)
  103. VALUES({(short)EsaLevel.DISTRICT}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {esaBaseLine.GradeId}, {(short)MultCourse.TOTAL}, {totalAvgScore}, {totalLineAvgScore}, {totalLineScore}, {totalRelativeDiff});
  104. -- 单科
  105. INSERT INTO esa_line_course_score(esa_level, esa_line_level, esa_plan_id, esa_base_line_id, grade_id, course_id, avg_score, line_avg_score, line_score, relative_diff)
  106. SELECT {(short)EsaLevel.DISTRICT}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {esaBaseLine.GradeId}, T1.course_id, T2.avg_course_score, T1.avg_line_course_score, T1.course_line_score, ROUND((T1.course_line_score - T2.avg_course_score) / T1.course_line_score, 8) AS relative_diff
  107. FROM
  108. (
  109. SELECT T1.course_id, ROUND(AVG(T1.score), 2) AS avg_line_course_score, ROUND(ROUND(AVG(T1.score), 2) * {factor}, 2) AS course_line_score
  110. FROM
  111. (
  112. SELECT T1.exam_student_id, T1.course_id, T1.score
  113. FROM exam_score AS T1
  114. {whereSql}
  115. ) AS T1
  116. JOIN
  117. (
  118. SELECT T1.exam_student_id
  119. FROM
  120. (
  121. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  122. FROM exam_score AS T1
  123. {whereSql}
  124. GROUP BY T1.exam_student_id
  125. ) AS T1
  126. WHERE T1.total_score >= {totalLineScore}
  127. ) AS T2 ON T1.exam_student_id = T2.exam_student_id
  128. GROUP BY T1.course_id
  129. ) AS T1
  130. JOIN
  131. (
  132. SELECT T1.course_id, ROUND(AVG(T1.score), 2) AS avg_course_score
  133. FROM exam_score AS T1
  134. {whereSql}
  135. GROUP BY T1.course_id
  136. ) AS T2 ON T1.course_id = T2.course_id;
  137. ");
  138. // 全区
  139. await rep.SqlNonQueryAsync(@$"
  140. INSERT INTO esa_line_total(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, grade_id, line_count, total_count, line_rate, factor)
  141. SELECT {(short)EsaLevel.DISTRICT}, {(short)EsaDataScopeType.TOTAL}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {esaBaseLine.GradeId}, COUNT(1) AS line_count, T2.total_count, COUNT(1) / T2.total_count, 0
  142. FROM
  143. (
  144. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  145. FROM exam_score AS T1
  146. {whereSql}
  147. GROUP BY T1.exam_student_id
  148. ) AS T1
  149. JOIN
  150. (
  151. SELECT COUNT(1) as total_count
  152. FROM
  153. (
  154. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  155. FROM exam_score AS T1
  156. {whereSql}
  157. GROUP BY T1.exam_student_id
  158. ) AS T1
  159. ) AS T2 ON 1 = 1
  160. WHERE T1.total_score >= {totalLineScore};
  161. ");
  162. // 学校
  163. await rep.SqlNonQueryAsync(@$"
  164. INSERT INTO esa_line_total(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, grade_id, sys_org_id, line_count, total_count, line_rate, factor)
  165. SELECT {(short)EsaLevel.DISTRICT}, {(short)EsaDataScopeType.ORG}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {esaBaseLine.GradeId}, T1.sys_org_id, COUNT(1) AS line_count, T2.total_count, COUNT(1) / T2.total_count, 0
  166. FROM
  167. (
  168. SELECT T1.sys_org_id, T1.exam_student_id, SUM(T1.score) AS total_score
  169. FROM exam_score AS T1
  170. {whereSql}
  171. GROUP BY T1.sys_org_id, T1.exam_student_id
  172. ) AS T1
  173. JOIN
  174. (
  175. SELECT T1.sys_org_id, COUNT(1) as total_count
  176. FROM
  177. (
  178. SELECT T1.sys_org_id, T1.exam_student_id, SUM(T1.score) AS total_score
  179. FROM exam_score AS T1
  180. {whereSql}
  181. GROUP BY T1.sys_org_id, T1.exam_student_id
  182. ) AS T1
  183. GROUP BY T1.sys_org_id
  184. ) AS T2 ON T1.sys_org_id = T2.sys_org_id
  185. WHERE T1.total_score >= {totalLineScore}
  186. GROUP BY T1.sys_org_id;
  187. ");
  188. // 班级
  189. await rep.SqlNonQueryAsync(@$"
  190. INSERT INTO esa_line_total(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, grade_id, sys_org_id, school_class_id, class_number, line_count, total_count, line_rate, factor)
  191. SELECT {(short)EsaLevel.DISTRICT}, {(short)EsaDataScopeType.CLASS}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {esaBaseLine.GradeId}, T1.sys_org_id, T1.school_class_id, T1.class_number, COUNT(1) AS line_count, T2.total_count, COUNT(1) / T2.total_count, 0
  192. FROM
  193. (
  194. SELECT T1.sys_org_id, T1.school_class_id, T1.class_number, T1.exam_student_id, SUM(T1.score) AS total_score
  195. FROM exam_score AS T1
  196. {whereSql}
  197. GROUP BY T1.sys_org_id, T1.school_class_id, T1.class_number, T1.exam_student_id
  198. ) AS T1
  199. JOIN
  200. (
  201. SELECT T1.sys_org_id, T1.school_class_id, T1.class_number, COUNT(1) as total_count
  202. FROM
  203. (
  204. SELECT T1.sys_org_id, T1.school_class_id, T1.class_number, T1.exam_student_id, SUM(T1.score) AS total_score
  205. FROM exam_score AS T1
  206. {whereSql}
  207. GROUP BY T1.sys_org_id, T1.school_class_id, T1.class_number, T1.exam_student_id
  208. ) AS T1
  209. GROUP BY T1.sys_org_id, T1.school_class_id, T1.class_number
  210. ) AS T2 ON T1.sys_org_id = T2.sys_org_id AND T1.school_class_id = T2.school_class_id AND T1.class_number = T2.class_number
  211. WHERE T1.total_score >= {totalLineScore}
  212. GROUP BY T1.sys_org_id, T1.school_class_id, T1.class_number;
  213. ");
  214. #endregion
  215. #region 学科上线
  216. var courseLines = await rep.Change<EsaLineCourseScore>().DetachedEntities
  217. .Where(t => t.EsaPlanId == esaPlanId &&
  218. t.EsaBaseLineId == esaBaseLine.Id &&
  219. t.EsaLevel == EsaLevel.DISTRICT &&
  220. t.EsaLineLevel == esaBaseLine.EsaLineLevel &&
  221. t.GradeId == esaBaseLine.GradeId &&
  222. t.CourseId != (short)MultCourse.TOTAL
  223. ).ToListAsync();
  224. foreach (var courseLine in courseLines)
  225. {
  226. // 单科条件
  227. var courseWhereSql = $"{whereBaseSql} AND T1.course_id = {courseLine.CourseId}";
  228. // 全区 - 单上线
  229. await rep.SqlNonQueryAsync(@$"
  230. INSERT INTO esa_line_course(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, course_id, grade_id, line_count, total_count, line_rate, is_double_line)
  231. SELECT {(short)EsaLevel.DISTRICT}, {(short)EsaDataScopeType.TOTAL}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {courseLine.CourseId}, {esaBaseLine.GradeId}, T1.line_count, T2.total_count, T1.line_count / T2.total_count, 0
  232. FROM
  233. (
  234. SELECT COUNT(1) AS line_count
  235. FROM exam_score AS T1
  236. {courseWhereSql} AND T1.score >= {courseLine.LineScore}
  237. ) AS T1
  238. JOIN
  239. (
  240. SELECT COUNT(1) as total_count
  241. FROM exam_score AS T1
  242. {courseWhereSql}
  243. ) AS T2 ON 1 = 1;
  244. ");
  245. // 全区 - 双上线
  246. await rep.SqlNonQueryAsync(@$"
  247. INSERT INTO esa_line_course(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, course_id, grade_id, line_count, total_count, line_rate, is_double_line)
  248. SELECT {(short)EsaLevel.DISTRICT}, {(short)EsaDataScopeType.TOTAL}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {courseLine.CourseId}, {esaBaseLine.GradeId}, T1.line_count, T2.total_count, T1.line_count / T2.total_count, 1
  249. FROM
  250. (
  251. SELECT COUNT(1) AS line_count
  252. FROM
  253. (
  254. SELECT T1.exam_student_id, T1.score
  255. FROM exam_score AS T1
  256. {courseWhereSql}
  257. ) AS T1
  258. JOIN
  259. (
  260. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  261. FROM exam_score AS T1
  262. {whereSql}
  263. GROUP BY T1.exam_student_id
  264. ) AS T2 ON T1.exam_student_id = T2.exam_student_id
  265. WHERE T1.score >= {courseLine.LineScore} AND T2.total_score >= {totalLineScore}
  266. ) AS T1
  267. JOIN
  268. (
  269. SELECT COUNT(1) as total_count
  270. FROM exam_score AS T1
  271. {courseWhereSql}
  272. ) AS T2 ON 1 = 1;
  273. ");
  274. // 学校 - 单上线
  275. await rep.SqlNonQueryAsync(@$"
  276. INSERT INTO esa_line_course(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, course_id, grade_id, sys_org_id, line_count, total_count, line_rate, is_double_line)
  277. SELECT {(short)EsaLevel.DISTRICT}, {(short)EsaDataScopeType.ORG}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {courseLine.CourseId}, {esaBaseLine.GradeId}, T1.sys_org_id, T1.line_count, T2.total_count, T1.line_count / T2.total_count, 0
  278. FROM
  279. (
  280. SELECT T1.sys_org_id, COUNT(1) AS line_count
  281. FROM exam_score AS T1
  282. {courseWhereSql} AND T1.score >= {courseLine.LineScore}
  283. GROUP BY T1.sys_org_id
  284. ) AS T1
  285. JOIN
  286. (
  287. SELECT T1.sys_org_id, COUNT(1) as total_count
  288. FROM exam_score AS T1
  289. {courseWhereSql}
  290. GROUP BY T1.sys_org_id
  291. ) AS T2 ON T1.sys_org_id = T2.sys_org_id;
  292. ");
  293. // 学校 - 双上线
  294. await rep.SqlNonQueryAsync(@$"
  295. INSERT INTO esa_line_course(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, course_id, grade_id, sys_org_id, line_count, total_count, line_rate, is_double_line)
  296. SELECT {(short)EsaLevel.DISTRICT}, {(short)EsaDataScopeType.ORG}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {courseLine.CourseId}, {esaBaseLine.GradeId}, T1.sys_org_id, T1.line_count, T2.total_count, T1.line_count / T2.total_count, 1
  297. FROM
  298. (
  299. SELECT T1.sys_org_id, COUNT(1) AS line_count
  300. FROM
  301. (
  302. SELECT T1.sys_org_id, T1.exam_student_id, T1.score
  303. FROM exam_score AS T1
  304. {courseWhereSql}
  305. ) AS T1
  306. JOIN
  307. (
  308. SELECT T1.sys_org_id, T1.exam_student_id, SUM(T1.score) AS total_score
  309. FROM exam_score AS T1
  310. {whereSql}
  311. GROUP BY T1.sys_org_id, T1.exam_student_id
  312. ) AS T2 ON T1.sys_org_id = T2.sys_org_id AND T1.exam_student_id = T2.exam_student_id
  313. WHERE T1.score >= {courseLine.LineScore} AND T2.total_score >= {totalLineScore}
  314. GROUP BY T1.sys_org_id
  315. ) AS T1
  316. JOIN
  317. (
  318. SELECT T1.sys_org_id, COUNT(1) as total_count
  319. FROM exam_score AS T1
  320. {courseWhereSql}
  321. GROUP BY T1.sys_org_id
  322. ) AS T2 ON T1.sys_org_id = T2.sys_org_id;
  323. ");
  324. // 班级 - 单上线
  325. await rep.SqlNonQueryAsync(@$"
  326. INSERT INTO esa_line_course(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, course_id, grade_id, sys_org_id, school_class_id, class_number, line_count, total_count, line_rate, is_double_line)
  327. SELECT {(short)EsaLevel.DISTRICT}, {(short)EsaDataScopeType.CLASS}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {courseLine.CourseId}, {esaBaseLine.GradeId}, T1.sys_org_id, T1.school_class_id, T1.class_number, T1.line_count, T2.total_count, T1.line_count / T2.total_count, 0
  328. FROM
  329. (
  330. SELECT T1.sys_org_id, T1.school_class_id, T1.class_number, COUNT(1) AS line_count
  331. FROM exam_score AS T1
  332. {courseWhereSql} AND T1.score >= {courseLine.LineScore}
  333. GROUP BY T1.sys_org_id, T1.school_class_id, T1.class_number
  334. ) AS T1
  335. JOIN
  336. (
  337. SELECT T1.sys_org_id, T1.school_class_id, T1.class_number, COUNT(1) as total_count
  338. FROM exam_score AS T1
  339. {courseWhereSql}
  340. GROUP BY T1.sys_org_id, T1.school_class_id, T1.class_number
  341. ) AS T2 ON T1.sys_org_id = T2.sys_org_id AND T1.school_class_id = T2.school_class_id AND T1.class_number = T2.class_number;
  342. ");
  343. // 班级 - 双上线
  344. await rep.SqlNonQueryAsync(@$"
  345. INSERT INTO esa_line_course(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, course_id, grade_id, sys_org_id, school_class_id, class_number, line_count, total_count, line_rate, is_double_line)
  346. SELECT {(short)EsaLevel.DISTRICT}, {(short)EsaDataScopeType.CLASS}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {courseLine.CourseId}, {esaBaseLine.GradeId}, T1.sys_org_id, T1.school_class_id, T1.class_number, T1.line_count, T2.total_count, T1.line_count / T2.total_count, 1
  347. FROM
  348. (
  349. SELECT T1.sys_org_id, T1.school_class_id, T1.class_number, COUNT(1) AS line_count
  350. FROM
  351. (
  352. SELECT T1.sys_org_id, T1.school_class_id, T1.class_number, T1.exam_student_id, T1.score
  353. FROM exam_score AS T1
  354. {courseWhereSql}
  355. ) AS T1
  356. JOIN
  357. (
  358. SELECT T1.sys_org_id, T1.school_class_id, T1.class_number, T1.exam_student_id, SUM(T1.score) AS total_score
  359. FROM exam_score AS T1
  360. {whereSql}
  361. GROUP BY T1.sys_org_id, T1.school_class_id, T1.class_number, T1.exam_student_id
  362. ) AS T2 ON T1.sys_org_id = T2.sys_org_id AND T1.school_class_id = T2.school_class_id AND T1.class_number = T2.class_number AND T1.exam_student_id = T2.exam_student_id
  363. WHERE T1.score >= {courseLine.LineScore} AND T2.total_score >= {totalLineScore}
  364. GROUP BY T1.sys_org_id, T1.school_class_id, T1.class_number
  365. ) AS T1
  366. JOIN
  367. (
  368. SELECT T1.sys_org_id, T1.school_class_id, T1.class_number, COUNT(1) as total_count
  369. FROM exam_score AS T1
  370. {courseWhereSql}
  371. GROUP BY T1.sys_org_id, T1.school_class_id, T1.class_number
  372. ) AS T2 ON T1.sys_org_id = T2.sys_org_id AND T1.school_class_id = T2.school_class_id AND T1.class_number = T2.class_number;
  373. ");
  374. }
  375. #endregion
  376. #endregion
  377. #region 学校分析
  378. var orgTotalLines = await rep.Change<EsaLineTotal>().DetachedEntities
  379. .Where(t => t.EsaLevel == EsaLevel.DISTRICT &&
  380. t.EsaLineLevel == esaBaseLine.EsaLineLevel &&
  381. t.EsaDataScopeType == EsaDataScopeType.ORG &&
  382. t.GradeId == esaBaseLine.GradeId
  383. ).OrderBy(t => t.SysOrgId).ToListAsync();
  384. foreach (var orgTotalLine in orgTotalLines)
  385. {
  386. // 构造取数条件
  387. var orgWhereBaseSql = $"WHERE T1.exam_plan_id = {plan.ExamPlanId} AND T1.grade_id = {esaBaseLine.GradeId} AND T1.score > 0 AND T1.sys_org_id = {orgTotalLine.SysOrgId}";
  388. var orgWhereSql = $"{orgWhereBaseSql} AND T1.course_id IN ({courseIds})";
  389. #region 总分划线
  390. // 总学生数量
  391. var orgTotalCount = await rep.SqlScalarAsync<int>($@"
  392. SELECT COUNT(1) AS total_count
  393. FROM
  394. (
  395. SELECT T1.exam_student_id
  396. FROM exam_score AS T1
  397. {orgWhereSql}
  398. GROUP BY T1.exam_student_id
  399. ) AS T1;
  400. ");
  401. // 总分上线分
  402. var orgTotalLineScore = await rep.SqlScalarAsync<decimal>($@"
  403. SELECT MIN(total_score) AS line_score
  404. FROM
  405. (
  406. SELECT ROW_NUMBER() OVER(ORDER BY total_score DESC) AS rn, total_score
  407. FROM
  408. (
  409. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  410. FROM exam_score AS T1
  411. {orgWhereSql}
  412. GROUP BY T1.exam_student_id
  413. ) AS T1
  414. ) AS T1
  415. WHERE T1.rn <= ROUND({orgTotalCount} * {orgTotalLine.LineRate}, 0);
  416. ");
  417. // 总分上线均分
  418. var orgTotalLineAvgScore = Math.Round(await rep.SqlScalarAsync<decimal>(@$"
  419. SELECT AVG(T1.total_score) AS line_avg_score
  420. FROM
  421. (
  422. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  423. FROM exam_score AS T1
  424. {orgWhereSql}
  425. GROUP BY T1.exam_student_id
  426. ) AS T1
  427. WHERE T1.total_score >= {orgTotalLineScore};
  428. "), 2);
  429. // 更新有效系数
  430. var orgFactor = Math.Round(orgTotalLineScore / orgTotalLineAvgScore, 8);
  431. await rep.SqlNonQueryAsync($"UPDATE esa_line_total SET factor = {orgFactor} WHERE id = {orgTotalLine.Id}");
  432. // 实际上线人数
  433. var orgFactLineCount = await rep.SqlScalarAsync($@"
  434. SELECT COUNT(1) AS line_count
  435. FROM
  436. (
  437. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  438. FROM exam_score AS T1
  439. {orgWhereSql}
  440. GROUP BY T1.exam_student_id
  441. ) AS T1
  442. WHERE T1.total_score >= {orgTotalLineScore};
  443. ");
  444. // 总均分
  445. var orgTotalAvgScore = Math.Round(await rep.SqlScalarAsync<decimal>(@$"
  446. SELECT AVG(total_score) AS avg_score
  447. FROM
  448. (
  449. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  450. FROM exam_score AS T1
  451. {orgWhereSql}
  452. GROUP BY T1.exam_student_id
  453. ) AS T1;
  454. "), 2);
  455. // 学科有效分
  456. var orgTotalRelativeDiff = Math.Round((orgTotalLineScore - orgTotalAvgScore) / orgTotalLineScore, 8);
  457. await rep.SqlNonQueryAsync(@$"
  458. -- 总分
  459. INSERT INTO esa_line_course_score(esa_level, esa_line_level, esa_plan_id, esa_base_line_id, grade_id, sys_org_id, course_id, avg_score, line_avg_score, line_score, relative_diff)
  460. VALUES({(short)EsaLevel.ORG}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {esaBaseLine.GradeId}, {orgTotalLine.SysOrgId}, {(short)MultCourse.TOTAL}, {orgTotalAvgScore}, {orgTotalLineAvgScore}, {orgTotalLineScore}, {orgTotalRelativeDiff});
  461. -- 单科
  462. INSERT INTO esa_line_course_score(esa_level, esa_line_level, esa_plan_id, esa_base_line_id, grade_id, sys_org_id, course_id, avg_score, line_avg_score, line_score, relative_diff)
  463. SELECT {(short)EsaLevel.ORG}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {esaBaseLine.GradeId}, {orgTotalLine.SysOrgId}, T1.course_id, T2.avg_course_score, T1.avg_line_course_score, T1.course_line_score, ROUND((T1.course_line_score - T2.avg_course_score) / T1.course_line_score, 8) AS relative_diff
  464. FROM
  465. (
  466. SELECT T1.course_id, ROUND(AVG(T1.score), 2) AS avg_line_course_score, ROUND(ROUND(AVG(T1.score), 2) * {orgFactor}, 2) AS course_line_score
  467. FROM
  468. (
  469. SELECT T1.exam_student_id, T1.course_id, T1.score
  470. FROM exam_score AS T1
  471. {orgWhereSql}
  472. ) AS T1
  473. JOIN
  474. (
  475. SELECT T1.exam_student_id
  476. FROM
  477. (
  478. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  479. FROM exam_score AS T1
  480. {orgWhereSql}
  481. GROUP BY T1.exam_student_id
  482. ) AS T1
  483. WHERE T1.total_score >= {orgTotalLineScore}
  484. ) AS T2 ON T1.exam_student_id = T2.exam_student_id
  485. GROUP BY T1.course_id
  486. ) AS T1
  487. JOIN
  488. (
  489. SELECT T1.course_id, ROUND(AVG(T1.score), 2) AS avg_course_score
  490. FROM exam_score AS T1
  491. {orgWhereSql}
  492. GROUP BY T1.course_id
  493. ) AS T2 ON T1.course_id = T2.course_id;
  494. ");
  495. // 学校
  496. await rep.SqlNonQueryAsync(@$"
  497. INSERT INTO esa_line_total(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, grade_id, sys_org_id, line_count, total_count, line_rate, factor)
  498. SELECT {(short)EsaLevel.ORG}, {(short)EsaDataScopeType.ORG}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {esaBaseLine.GradeId}, {orgTotalLine.SysOrgId}, COUNT(1) AS line_count, T2.total_count, COUNT(1) / T2.total_count, 0
  499. FROM
  500. (
  501. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  502. FROM exam_score AS T1
  503. {orgWhereSql}
  504. GROUP BY T1.exam_student_id
  505. ) AS T1
  506. JOIN
  507. (
  508. SELECT COUNT(1) as total_count
  509. FROM
  510. (
  511. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  512. FROM exam_score AS T1
  513. {orgWhereSql}
  514. GROUP BY T1.exam_student_id
  515. ) AS T1
  516. ) AS T2 ON 1 = 1
  517. WHERE T1.total_score >= {orgTotalLineScore};
  518. ");
  519. // 班级
  520. await rep.SqlNonQueryAsync(@$"
  521. INSERT INTO esa_line_total(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, grade_id, sys_org_id, school_class_id, class_number, line_count, total_count, line_rate, factor)
  522. SELECT {(short)EsaLevel.ORG}, {(short)EsaDataScopeType.CLASS}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {esaBaseLine.GradeId}, {orgTotalLine.SysOrgId}, T1.school_class_id, T1.class_number, COUNT(1) AS line_count, T2.total_count, COUNT(1) / T2.total_count, 0
  523. FROM
  524. (
  525. SELECT T1.school_class_id, T1.class_number, T1.exam_student_id, SUM(T1.score) AS total_score
  526. FROM exam_score AS T1
  527. {orgWhereSql}
  528. GROUP BY T1.school_class_id, T1.class_number, T1.exam_student_id
  529. ) AS T1
  530. JOIN
  531. (
  532. SELECT T1.school_class_id, T1.class_number, COUNT(1) as total_count
  533. FROM
  534. (
  535. SELECT T1.school_class_id, T1.class_number, T1.exam_student_id, SUM(T1.score) AS total_score
  536. FROM exam_score AS T1
  537. {orgWhereSql}
  538. GROUP BY T1.school_class_id, T1.class_number, T1.exam_student_id
  539. ) AS T1
  540. GROUP BY T1.school_class_id, T1.class_number
  541. ) AS T2 ON T1.school_class_id = T2.school_class_id AND T1.class_number = T2.class_number
  542. WHERE T1.total_score >= {orgTotalLineScore}
  543. GROUP BY T1.school_class_id, T1.class_number;
  544. ");
  545. #endregion
  546. #region 学科划线
  547. var orgCourseLines = await rep.Change<EsaLineCourseScore>().DetachedEntities
  548. .Where(t => t.EsaPlanId == esaPlanId &&
  549. t.EsaBaseLineId == esaBaseLine.Id &&
  550. t.EsaLevel == EsaLevel.ORG &&
  551. t.EsaLineLevel == esaBaseLine.EsaLineLevel &&
  552. t.GradeId == esaBaseLine.GradeId &&
  553. t.SysOrgId == orgTotalLine.SysOrgId &&
  554. t.CourseId != (short)MultCourse.TOTAL
  555. ).ToListAsync();
  556. foreach (var orgCourseLine in orgCourseLines)
  557. {
  558. // 单科条件
  559. var orgCourseWhereSql = $"{orgWhereBaseSql} AND T1.course_id = {orgCourseLine.CourseId}";
  560. // 学校 - 单上线
  561. await rep.SqlNonQueryAsync(@$"
  562. INSERT INTO esa_line_course(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, course_id, grade_id, sys_org_id, line_count, total_count, line_rate, is_double_line)
  563. SELECT {(short)EsaLevel.ORG}, {(short)EsaDataScopeType.ORG}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {orgCourseLine.CourseId}, {esaBaseLine.GradeId}, {orgTotalLine.SysOrgId}, T1.line_count, T2.total_count, T1.line_count / T2.total_count, 0
  564. FROM
  565. (
  566. SELECT COUNT(1) AS line_count
  567. FROM exam_score AS T1
  568. {orgCourseWhereSql} AND T1.score >= {orgCourseLine.LineScore}
  569. ) AS T1
  570. JOIN
  571. (
  572. SELECT COUNT(1) as total_count
  573. FROM exam_score AS T1
  574. {orgCourseWhereSql}
  575. ) AS T2 ON 1 = 1;
  576. ");
  577. // 学校 - 双上线
  578. await rep.SqlNonQueryAsync(@$"
  579. INSERT INTO esa_line_course(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, course_id, grade_id, sys_org_id, line_count, total_count, line_rate, is_double_line)
  580. SELECT {(short)EsaLevel.ORG}, {(short)EsaDataScopeType.ORG}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {orgCourseLine.CourseId}, {esaBaseLine.GradeId}, {orgTotalLine.SysOrgId}, T1.line_count, T2.total_count, T1.line_count / T2.total_count, 1
  581. FROM
  582. (
  583. SELECT COUNT(1) AS line_count
  584. FROM
  585. (
  586. SELECT T1.exam_student_id, T1.score
  587. FROM exam_score AS T1
  588. {orgCourseWhereSql}
  589. ) AS T1
  590. JOIN
  591. (
  592. SELECT T1.exam_student_id, SUM(T1.score) AS total_score
  593. FROM exam_score AS T1
  594. {orgWhereSql}
  595. GROUP BY T1.exam_student_id
  596. ) AS T2 ON T1.exam_student_id = T2.exam_student_id
  597. WHERE T1.score >= {orgCourseLine.LineScore} AND T2.total_score >= {orgTotalLineScore}
  598. ) AS T1
  599. JOIN
  600. (
  601. SELECT COUNT(1) as total_count
  602. FROM exam_score AS T1
  603. {orgCourseWhereSql}
  604. ) AS T2 ON 1 = 1;
  605. ");
  606. // 班级 - 单上线
  607. await rep.SqlNonQueryAsync(@$"
  608. INSERT INTO esa_line_course(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, course_id, grade_id, sys_org_id, school_class_id, class_number, line_count, total_count, line_rate, is_double_line)
  609. SELECT {(short)EsaLevel.ORG}, {(short)EsaDataScopeType.CLASS}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {orgCourseLine.CourseId}, {esaBaseLine.GradeId}, {orgTotalLine.SysOrgId}, T1.school_class_id, T1.class_number, T1.line_count, T2.total_count, T1.line_count / T2.total_count, 0
  610. FROM
  611. (
  612. SELECT T1.school_class_id, T1.class_number, COUNT(1) AS line_count
  613. FROM exam_score AS T1
  614. {orgCourseWhereSql} AND T1.score >= {orgCourseLine.LineScore}
  615. GROUP BY T1.school_class_id, T1.class_number
  616. ) AS T1
  617. JOIN
  618. (
  619. SELECT T1.school_class_id, T1.class_number, COUNT(1) as total_count
  620. FROM exam_score AS T1
  621. {orgCourseWhereSql}
  622. GROUP BY T1.school_class_id, T1.class_number
  623. ) AS T2 ON T1.school_class_id = T2.school_class_id AND T1.class_number = T2.class_number;
  624. ");
  625. // 班级 - 双上线
  626. await rep.SqlNonQueryAsync(@$"
  627. INSERT INTO esa_line_course(esa_level, esa_data_scope_type, esa_line_level, esa_plan_id, esa_base_line_id, course_id, grade_id, sys_org_id, school_class_id, class_number, line_count, total_count, line_rate, is_double_line)
  628. SELECT {(short)EsaLevel.ORG}, {(short)EsaDataScopeType.CLASS}, {(short)esaBaseLine.EsaLineLevel}, {esaPlanId}, {esaBaseLine.Id}, {orgCourseLine.CourseId}, {esaBaseLine.GradeId}, {orgTotalLine.SysOrgId}, T1.school_class_id, T1.class_number, T1.line_count, T2.total_count, T1.line_count / T2.total_count, 1
  629. FROM
  630. (
  631. SELECT T1.school_class_id, T1.class_number, COUNT(1) AS line_count
  632. FROM
  633. (
  634. SELECT T1.school_class_id, T1.class_number, T1.exam_student_id, T1.score
  635. FROM exam_score AS T1
  636. {orgCourseWhereSql}
  637. ) AS T1
  638. JOIN
  639. (
  640. SELECT T1.school_class_id, T1.class_number, T1.exam_student_id, SUM(T1.score) AS total_score
  641. FROM exam_score AS T1
  642. {orgWhereSql}
  643. GROUP BY T1.school_class_id, T1.class_number, T1.exam_student_id
  644. ) AS T2 ON T1.school_class_id = T2.school_class_id AND T1.class_number = T2.class_number AND T1.exam_student_id = T2.exam_student_id
  645. WHERE T1.score >= {orgCourseLine.LineScore} AND T2.total_score >= {orgTotalLineScore}
  646. GROUP BY T1.school_class_id, T1.class_number
  647. ) AS T1
  648. JOIN
  649. (
  650. SELECT T1.school_class_id, T1.class_number, COUNT(1) as total_count
  651. FROM exam_score AS T1
  652. {orgCourseWhereSql}
  653. GROUP BY T1.school_class_id, T1.class_number
  654. ) AS T2 ON T1.school_class_id = T2.school_class_id AND T1.class_number = T2.class_number;
  655. ");
  656. }
  657. #endregion
  658. }
  659. #endregion
  660. // 更新状态
  661. await rep.SqlNonQueryAsync($"UPDATE esa_base_line SET status = {(short)ProcessingStatus.SUCCESSFUL} WHERE id = {esaBaseLine.Id}");
  662. }
  663. catch (Exception)
  664. {
  665. // 更新状态
  666. await rep.SqlNonQueryAsync($"UPDATE esa_base_line SET status = {(short)ProcessingStatus.FAILED} WHERE id = {esaBaseLine.Id}");
  667. throw;
  668. }
  669. }
  670. // 更新状态
  671. await rep.SqlNonQueryAsync($"UPDATE esa_plan SET status = {(short)ProcessingStatus.SUCCESSFUL} WHERE id = {esaPlanId}");
  672. }
  673. catch (Exception)
  674. {
  675. // 更新状态
  676. await rep.SqlNonQueryAsync($"UPDATE esa_plan SET status = {(short)ProcessingStatus.FAILED} WHERE id = {esaPlanId}");
  677. throw;
  678. }
  679. }
  680. }