From 1298e748f2e1284bff2cceae402956fdda089c49 Mon Sep 17 00:00:00 2001 From: p31729568 Date: Sun, 5 May 2019 17:00:49 +0800 Subject: [PATCH] modify school statistic service to decrease response time --- .../managements/schools_controller.rb | 26 +++--- app/models/course.rb | 2 + app/models/school.rb | 4 + .../management/school_report_service.rb | 83 +++++++++++++++---- .../schools/_statistics_list.html.erb | 18 ++-- .../schools/statistics_xlsx.xlsx.axlsx | 22 ++--- 6 files changed, 105 insertions(+), 50 deletions(-) diff --git a/app/controllers/managements/schools_controller.rb b/app/controllers/managements/schools_controller.rb index 9ca9a56e..f27e00ae 100644 --- a/app/controllers/managements/schools_controller.rb +++ b/app/controllers/managements/schools_controller.rb @@ -4,11 +4,12 @@ class Managements::SchoolsController < Managements::BaseController def statistics @sub_type = 1 - params[:sort_by] ||= :teacher_count - params[:sort_direction] ||= :desc + params[:sort_by] = :teacher_count if params[:sort_by].blank? + params[:sort_direction] = :desc if params[:sort_direction].blank? - schools = Management::SchoolReportService.new(params).call - @schools = paginateHelper schools + service = Management::SchoolReportService.new(params) + @obj_count, @schools = service.call + @obj_pages = Paginator.new(@obj_count, 20, params[:page]) respond_to do |format| format.html { load_statistic_total } @@ -19,20 +20,20 @@ class Managements::SchoolsController < Managements::BaseController def data_grow @sub_type = 2 params[:data_type] ||= 'grow' - params[:sort_by] ||= :teacher_increase_count - params[:sort_direction] ||= :desc + params[:sort_by] = :teacher_increase_count if params[:sort_by].blank? + params[:sort_direction] = :desc if params[:sort_direction].blank? service = Management::SchoolDataGrowService.new(params) @grow_summary = service.grow_summary @obj_count, @reports = service.call - @obj_pages = Paginator.new(@obj_count, Management::SchoolDataGrowService::PAGE_SIZE, params[:page]) + @obj_pages = Paginator.new(@obj_count, 20, params[:page]) end def data_contrast params[:contrast_column] = :teacher_increase_count if params[:contrast_column].blank? params[:sort_direction] ||= :desc - params[:sort_by] ||= :percentage + params[:sort_by] = :percentage # 无对比日期时直接返回无数据页面 if useless_contrast_date_parameter? @@ -41,16 +42,17 @@ class Managements::SchoolsController < Managements::BaseController end @obj_count, @reports = Management::SchoolDataContrastService.new(params).call - @obj_pages = Paginator.new(@obj_count, Management::SchoolDataContrastService::PAGE_SIZE, params[:page]) + @obj_pages = Paginator.new(@obj_count, 20, params[:page]) rescue Management::SchoolDataContrastService::ParameterError raise '参数错误' end def statistics_xlsx - @schools = Management::SchoolReportService.new(params).call + params[:per_page] = 10000 + _count, @schools = Management::SchoolReportService.new(params).call - filename = ["学校统计总表", params[:keyword], Time.zone.now.strftime('%Y%m%d%H%M%S')].join('-') << ".xlsx" - render xlsx: "statistics_xlsx", filename: filename + filename = ['学校统计总表', params[:keyword], Time.zone.now.strftime('%Y%m%d%H%M%S')].join('-') << '.xlsx' + render xlsx: 'statistics_xlsx', filename: filename end private diff --git a/app/models/course.rb b/app/models/course.rb index 551dafe5..843d846d 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -56,6 +56,8 @@ class Course < ActiveRecord::Base has_many :course_homework_categories, :dependent => :destroy, :order => "CONVERT(name USING gbk) COLLATE gbk_chinese_ci ASC" has_many :homework_commons, :dependent => :destroy + has_many :shixun_homework_commons, class_name: 'HomeworkCommon', conditions: 'homework_type = 4' + has_many :other_homework_commons, class_name: 'HomeworkCommon', conditions: 'homework_type IN (1, 3)' has_many :homework_group_settings, :dependent => :destroy has_many :student_works, :through => :homework_commons, :dependent => :destroy diff --git a/app/models/school.rb b/app/models/school.rb index 227858a4..c5018191 100644 --- a/app/models/school.rb +++ b/app/models/school.rb @@ -6,6 +6,7 @@ class School < ActiveRecord::Base :identifier, :is_online, :video_desc, :video_name,:course_link, :course_name, :partner_id, :customer_id has_many :courses + has_many :active_courses, class_name: 'Course', conditions: 'is_end = false' has_many :departments, :dependent => :destroy has_many :shixun_schools, :dependent => :destroy has_many :shixuns, :through => :shixun_schools @@ -25,6 +26,9 @@ class School < ActiveRecord::Base # 报表信息 has_many :school_daily_reports + has_many :teacher_extensions, conditions: "identity = #{User::TEACHER}", class_name: 'UserExtensions' + has_many :student_extensions, conditions: "identity = #{User::STUDENT}", class_name: 'UserExtensions' + # 视频附件 acts_as_attachable diff --git a/app/services/management/school_report_service.rb b/app/services/management/school_report_service.rb index 5f50c5ec..4784db31 100644 --- a/app/services/management/school_report_service.rb +++ b/app/services/management/school_report_service.rb @@ -12,30 +12,85 @@ class Management::SchoolReportService end def call - schools = School.select(select_columns_sql) + schools = School.group('schools.id') keyword = params[:keyword].try(:to_s).try(:strip) if keyword.present? schools = schools.where("schools.name LIKE :keyword OR schools.id LIKE :keyword", keyword: "%#{keyword}%") end + count = schools.count.count + + # 根据排序字段进行查询 + schools = query_by_sort_column(schools, params[:sort_by]) schools = custom_sort(schools, params[:sort_by], params[:sort_direction]) - schools + schools = schools.limit(page_size).offset(offset) + # 查询并组装其它数据 + schools = package_other_data(schools) + + [count, schools] + end + + def package_other_data(schools) + ids = schools.map(&:id) + + student_map = UserExtensions.where(school_id: ids, identity: User::STUDENT).group(:school_id).count + teacher_map = UserExtensions.where(school_id: ids, identity: User::TEACHER).group(:school_id).count + + homeworks = HomeworkCommon.joins(:course) + shixun_homework_map = homeworks.where(homework_type: 4, courses: { school_id: ids }).group('school_id').count + other_homework_map = homeworks.where(homework_type: [1, 3], courses: { school_id: ids }).group('school_id').count + + courses = Course.where(school_id: ids).group('school_id') + course_map = courses.count + nearly_course_time_map = courses.joins(:course_activities).maximum('course_activities.updated_at') + active_course_map = courses.where(is_end: false).count + + schools.map do |school| + { + id: school.id, + name: school.name, + teacher_count: teacher_map[school.id], + student_count: student_map[school.id], + homework_count: shixun_homework_map[school.id], + other_homework_count: other_homework_map[school.id], + course_count: course_map[school.id], + nearly_course_time: nearly_course_time_map[school.id], + active_course_count: active_course_map[school.id], + } + end end private - def select_columns_sql - "schools.id, schools.name,"\ - "(SELECT COUNT(*) FROM user_extensions ue WHERE ue.school_id = schools.id AND ue.identity = #{User::STUDENT}) student_count,"\ - "(SELECT COUNT(*) FROM user_extensions ue WHERE ue.school_id = schools.id AND ue.identity = #{User::TEACHER}) teacher_count,"\ - "(SELECT COUNT(*) FROM homework_commons hc LEFT JOIN courses ON courses.id = hc.course_id "\ - "WHERE courses.school_id = schools.id AND hc.homework_type = 4) homework_count,"\ - "(SELECT COUNT(*) FROM homework_commons hc LEFT JOIN courses ON courses.id = hc.course_id "\ - "WHERE courses.school_id = schools.id AND hc.homework_type IN (1,3)) other_homework_count,"\ - "(SELECT COUNT(*) FROM courses cs WHERE cs.school_id = schools.id) course_count ,"\ - "(SELECT MAX(ca.updated_at) FROM course_activities ca LEFT JOIN courses cs ON cs.id = ca.course_id "\ - "WHERE cs.school_id = schools.id) nearly_course_time ,"\ - "(SELECT COUNT(*) FROM courses acs WHERE acs.school_id = schools.id AND acs.is_end = false) active_course_count" + def query_by_sort_column(schools, sort_by_column) + base_query_column = 'schools.id, schools.name' + + case sort_by_column.to_s + when 'teacher_count' then + schools.joins(:teacher_extensions).select("#{base_query_column}, COUNT(*) teacher_count") + when 'student_count' then + schools.joins(:student_extensions).select("#{base_query_column}, COUNT(*) student_count") + when 'homework_count' then + schools.joins(courses: :shixun_homework_commons).select("#{base_query_column}, COUNT(*) homework_count") + when 'other_homework_count' then + schools.joins(courses: :other_homework_commons).select("#{base_query_column}, COUNT(*) other_homework_count") + when 'course_count' then + schools.joins(:courses).select("#{base_query_column}, COUNT(*) course_count") + when 'nearly_course_time' then + schools.joins(courses: :course_activities).select("#{base_query_column}, MAX(course_activities.updated_at) nearly_course_time") + when 'active_course_count' then + schools.joins(:active_courses).select("#{base_query_column}, COUNT(*) active_course_count") + else + schools.joins(:teacher_extensions).select("#{base_query_column}, COUNT(*) teacher_count") + end + end + + def page_size + params[:per_page] || 20 + end + + def offset + (params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * page_size end end diff --git a/app/views/managements/schools/_statistics_list.html.erb b/app/views/managements/schools/_statistics_list.html.erb index cffb316c..53c13ed8 100644 --- a/app/views/managements/schools/_statistics_list.html.erb +++ b/app/views/managements/schools/_statistics_list.html.erb @@ -18,15 +18,15 @@ <% @schools.each_with_index do |school, index| %> <%= (@obj_pages.page - 1) * @obj_pages.per_page + index + 1 %> - <%= school['id'] %> - <%= school['name'] %> - <%= school['teacher_count'] %> - <%= school['student_count'] %> - <%= school['course_count'] %> - <%= school['active_course_count'] %> - <%= school['homework_count'] %> - <%= school['other_homework_count'] %> - <%= format_time school['nearly_course_time'] %> + <%= school[:id] %> + <%= school[:name] %> + <%= school[:teacher_count].to_i %> + <%= school[:student_count].to_i %> + <%= school[:course_count].to_i %> + <%= school[:active_course_count].to_i %> + <%= school[:homework_count].to_i %> + <%= school[:other_homework_count].to_i %> + <%= format_time school[:nearly_course_time] %> <% end %> diff --git a/app/views/managements/schools/statistics_xlsx.xlsx.axlsx b/app/views/managements/schools/statistics_xlsx.xlsx.axlsx index b68a817c..85f28531 100644 --- a/app/views/managements/schools/statistics_xlsx.xlsx.axlsx +++ b/app/views/managements/schools/statistics_xlsx.xlsx.axlsx @@ -1,20 +1,12 @@ wb = xlsx_package.workbook -wb.add_worksheet(name: "统计总表") do |sheet| +wb.add_worksheet(name: '统计总表') do |sheet| sheet.add_row %w(ID 单位名称 教师总人数 学生总人数 课堂总数 正在进行课堂数 实训作业总数 其它作业总数 动态时间) - total = @schools.count - buffer_size = 500 - times = total % 500 > 0 ? total / 500 + 1 : total / 500 - - times.times do |index| - schools = @schools.limit(buffer_size).offset(index * buffer_size) - - schools.each do |school| - sheet.add_row([ - school['id'].to_s, school['name'].to_s, school['teacher_count'].to_s, school['student_count'].to_s, - school['course_count'].to_s, school['active_course_count'].to_s, school['homework_count'].to_s, - school['other_homework_count'].to_s, format_time(school['nearly_course_time']) - ]) - end + @schools.each do |school| + sheet.add_row([ + school['id'].to_s, school['name'].to_s, (school['teacher_count'] || 0).to_s, (school['student_count'] || 0).to_s, + (school['course_count'] || 0).to_s, (school['active_course_count'] || 0).to_s, (school['homework_count'] || 0).to_s, + (school['other_homework_count'] || 0).to_s, format_time(school['nearly_course_time']) + ]) end end \ No newline at end of file