按列上的特定值分组以获得更快的执行时间 - SQL

Group By a specific value on a column for faster execution time - SQL

此代码完美运行,但执行时间很长,因为 attendance_03 的行数与 working_schedule_03 相同,后者确实需要每一行,因为 working_schedule_03 有轮班时间表像 8:00、9:00 等等,它是 attendance_03 已故员工的基础,attendance_03 有员工的实际工作时间,现在我想要的是分组working_schedule_03 table 中多个列中的某些值,即 emp_id 列和 t_in(轮班时间表)列,因为 t_in 不固定,员工更改时间表week 和其他人已经修复了 sched 和最后一个具有 "Regular" 值的 eve 列,并取消了 "Rest day" 值的分组,因此 attendance_03 将不会从具有休息日值的 eve 列中获取行。谢谢!

 SELECT 
    a.emp_id, COUNT(a.a_id) AS Cymon, b.t_in AS mt_in, c.last_name, c.first_name, e.dept_name, e.dept_id, f.l_id, f.loc
 FROM
     attendance_03 AS a
    LEFT JOIN 
      (SELECT * FROM working_schedule_03 WHERE d BETWEEN 16 AND 31 AND Y = 2015 AND eve="Regular") AS b ON b.emp_id = a.emp_id AND b.d = a.dd
    LEFT JOIN 
      employee_personal_info AS c ON c.emp_id = a.emp_id 
    LEFT JOIN 
      employee_information AS d ON d.emp_id = a.emp_id 
    LEFT JOIN 
      departments AS e ON e.dept_id = d.department 
    LEFT JOIN 
      employee_location AS f ON f.l_id = d.loc 
  WHERE a.yy = 2015 AND a.dd BETWEEN 16 AND 31 AND b.eve = "Regular" AND e.dept_id != 22
      AND
  CASE 
    WHEN b.t_in = "07:00" THEN HOUR(a.t_in) = "07" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "07:30" THEN HOUR(a.t_in) = "07" AND MINUTE(a.t_in) BETWEEN 31 AND 59 OR HOUR(a.t_in) = "08" AND MINUTE(a.t_in) BETWEEN 01 AND 30
    WHEN b.t_in = "08:00" THEN HOUR(a.t_in) = "08" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "08:30" THEN HOUR(a.t_in) = "08" AND MINUTE(a.t_in) BETWEEN 31 AND 59 OR HOUR(a.t_in) = "09" AND MINUTE(a.t_in) BETWEEN 01 AND 30
    WHEN b.t_in = "09:00" THEN HOUR(a.t_in) = "09" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "10:00" THEN HOUR(a.t_in) = "10" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "13:00" THEN HOUR(a.t_in) = "13" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "15:00" THEN HOUR(a.t_in) = "15" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "16:00" THEN HOUR(a.t_in) = "16" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "17:00" THEN HOUR(a.t_in) = "17" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "19:00" THEN HOUR(a.t_in) = "19" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "19:30" THEN HOUR(a.t_in) = "19" AND MINUTE(a.t_in) BETWEEN 31 AND 59 OR HOUR(a.t_in) = "20" AND MINUTE(a.t_in) BETWEEN 01 AND 30
    WHEN b.t_in = "20:00" THEN HOUR(a.t_in) = "20" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "21:00" THEN HOUR(a.t_in) = "21" AND MINUTE(a.t_in) BETWEEN 01 AND 59 
    WHEN b.t_in = "23:45" THEN HOUR(a.t_in) = "23" AND MINUTE(a.t_in) BETWEEN 46 AND 59 OR HOUR(a.t_in) = "20" AND MINUTE(a.t_in) BETWEEN 01 AND 45
  ELSE 0 END 
  GROUP BY a.emp_id
  HAVING COUNT(a.emp_id) > 1
  ORDER BY f.loc, e.dept_id, c.last_name ASC 

working_schedule_03 table

CREATE TABLE `working_schedule_03` (
  `id` mediumint(99) NOT NULL AUTO_INCREMENT,
  `start_date` datetime NOT NULL,
  `end_date` datetime NOT NULL,
  `username` varchar(255) NOT NULL,
  `m` varchar(9) NOT NULL,
  `d` varchar(9) NOT NULL,
  `y` varchar(9) NOT NULL,
  `emp_id` varchar(99) NOT NULL,
  `eve` varchar(99) NOT NULL,
  `t_in` varchar(99) NOT NULL,
  `t_out` varchar(99) NOT NULL,
  `emp_file` varchar(99) NOT NULL,
  `dt_plot` varchar(99) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=612993 DEFAULT CHARSET=latin1

attendance_03 table

CREATE TABLE `attendance_03` (
  `a_id` varchar(99) NOT NULL,
  `t_in` varchar(99) NOT NULL,
  `t_b1_out` varchar(99) NOT NULL,
  `t_b1_in` varchar(99) NOT NULL,
  `t_lb_out` varchar(99) NOT NULL,
  `t_lb_in` varchar(99) NOT NULL,
  `t_b2_out` varchar(99) NOT NULL,
  `t_b2_in` varchar(99) NOT NULL,
  `t_out` varchar(99) NOT NULL,
  `mu` varchar(99) NOT NULL,
  `status` varchar(99) NOT NULL,
  `mm` varchar(99) NOT NULL,
  `dd` varchar(99) NOT NULL,
  `yy` varchar(99) NOT NULL,
  `d_out` int(2) NOT NULL,
  `d_b1_out` int(2) NOT NULL,
  `d_b1_in` int(2) NOT NULL,
  `d_lb_out` int(2) NOT NULL,
  `d_lb_in` int(2) NOT NULL,
  `d_b2_out` int(2) NOT NULL,
  `d_b2_in` int(2) NOT NULL,
  `emp_id` varchar(99) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1

添加索引会显着加快速度:

  • working_schedule_03 会受益于 INDEX(Y, d, eve)
  • attendance_03 会受益于 INDEX(emp_id, dd)
  • employee_personal_infoemployee_informationINDEX(emp_id)
  • departments: INDEX(e.dept_id)
  • employee_location: INDEX(f.l_id)

删除 LEFT 除非您预计 'right' table 缺少匹配行。

第二次出现 AND b.eve = "Regular" 是多余的(因为第一次出现)。

子查询表示 SELECT *。如果您只列出必要的值 (emp_id, t_in, d)。

我对其他事情作呕:

  • 不要使用 VARCHAR 作为数字。
  • 考虑使用 TIME 次。 (但是 :00 秒可能有问题。)
  • 大的CASE几乎可以变成

    a.t_in >= b.t_in AND a.in < b.t_in + 间隔 60 分钟

  • 检查输出; COUNT(...) 的值可能比需要的大。