MySQL更新列,如果值被另一个表中的范围覆盖

时间:2018-09-26 22:43:51

标签: mysql

我有2个简单的表格。第一表包含工人的缺勤情况。

tbl_absences
+----+-------------+------------+-----------------------+
| id | id_employee | day_number | is_covered_by_a_range |
+----+-------------+------------+-----------------------+
|  1 |           1 |         18 |       true/false      |
|  2 |           1 |          3 |       true/false      |
|  3 |           2 |         21 |       true/false      |
|  4 |           1 |         13 |       true/false      |
|  5 |           2 |         22 |       true/false      |
|  6 |           1 |         10 |       true/false      |
|  7 |           1 |          7 |       true/false      |
.....

第二张表包含该工人患病并且是中间休假的时间段(介于range_startrange_end之间的天数)

tbl_sick_leave
+----+-------------+-------------+-----------+
| id | id_employee | range_start | range_end |
+----+-------------+-------------+-----------+
|  1 |           1 |           4 |         8 |
|  2 |           1 |          13 |        18 |
|  3 |           1 |          15 |        21 |
|  4 |           2 |           9 |        12 |
.....

我希望表is_covered_by_a_range中的列tbl_absences保留一个布尔值: true 如果该天被tbl_sick_leave中的任何范围所覆盖,并且<如果不是,则strong> false 。 为了仅针对工作程序1进行更新,我的方法是查询如下内容:

update tbl_absences AS a
SET a.is_covered_by_a_range=(EXISTS(
    SELECT * FROM tbl_sick_leave AS s 
    WHERE s.id_employee=1 AND a.day_number BETWEEN s.range_start AND s.range_end
))
WHERE a.id_employee=1

注意:tbl_sick_leave可以容纳一个涵盖特定日期的范围。 可以做得更好吗?对于大表,我担心这种查询的性能。

测试1

tbl_absences
+----+-------------+------------+-----------------------+
| id | id_employee | day_number | is_covered_by_a_range |
+----+-------------+------------+-----------------------+
|  1 |           1 |          5 |                    -1 |
|  2 |           1 |         10 |                    -1 |
+----+-------------+------------+-----------------------+

tbl_sick_leave
+----+-------------+-------------+-----------+
| id | id_employee | range_start | range_end |
+----+-------------+-------------+-----------+
|  1 |           1 |           2 |         6 |
+----+-------------+-------------+-----------+

使用此查询将更新两行:

update tbl_absences AS a
SET a.is_covered_by_a_range=(EXISTS(
    SELECT * FROM tbl_sick_leave AS s 
    WHERE s.id_employee=1 AND a.day_number BETWEEN s.range_start AND s.range_end
))
WHERE a.id_employee=1

结果(is_covered_by_a_range中的正确值):

tbl_absences
+----+-------------+------------+-----------------------+
| id | id_employee | day_number | is_covered_by_a_range |
+----+-------------+------------+-----------------------+
|  1 |           1 |          5 |                     1 |
|  2 |           1 |         10 |                     0 |
+----+-------------+------------+-----------------------+

1 个答案:

答案 0 :(得分:1)

您可以使用public int nextEven(int h){ int n = ThreadLocalRandom.current().nextInt(1 + (h / 2)); // 0 to (h / 2) inclusive return n * 2; // n * 2 is even (or zero). }

JOIN

很难预测性能,但是您当然应该从两个表中UPDATE tbl_absences AS a LEFT JOIN tbl_sick_leave AS s ON a.id_employee = s.id_employee AND a.day_number BETWEEN s.range_start AND s.range_end SET a.is_covered_by_a_range = s.id IS NOT NULL WHERE a.id_employee = 1 上的索引开始。如果这还不够好,那么在id_employee(id_employee, day_number上的复合索引可能会有所帮助。如果不是,请发布tbl_absences查询的输出。