按列上的特定值分组以获得更快的执行时间 - 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_info
和 employee_information
:INDEX(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(...)
的值可能比需要的大。
此代码完美运行,但执行时间很长,因为 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_info
和employee_information
:INDEX(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(...)
的值可能比需要的大。