假设我们有这个资源可用性表:
+-----------+-----------------------------------------------------------+
| date | obvious, the date |
| timeslot | we have 12 fixed 2-hour timeslots so this will be 1 to 12 |
| r1 | number of resource type 1 available during this timeslot |
| r2 | same, for resource type 2 |
| r3 | same, for resource type 3 |
+-----------+-----------------------------------------------------------+现在,我想看看我可以用来做job #43的所有可用的时隙。对于这项工作,我需要两个单元的r1,一个单位的r2,和三个单位的r3。假设任务需要一个时隙,我可以使用以下查询:
SELECT `date`, `timeslot` FROM `resource_availability`
WHERE
`r1` > '1' AND
`r2` > '0' AND
`r3` > '2'
ORDER BY 'date`, `timeslot`;但是,如果我有另一个作业,job #86需要3次才能完成,并且无法停止-重新启动,那么是否有可能通过查询获得安全的启动时间?
我目前正在检查我的while循环中的连续性,但我认为可以让查询这样做。
如果可能的话,我想知道哪一个更快、更有效率。为了进行效能评估,应该注意的是,此表作为一种位图经常被更新--也就是说,在每一项作业被调度时,资源可用性列都会被更新。
而且,很明显,这个系统的目的是允许检查什么-ifs。如果我的方法不是最优的,还有什么更好的选择吗?
如果最后一个问题太多,请忽略它,或者在评论中让我知道,我会删除它。
发布于 2012-07-11 05:13:14
呜呜..。我想出了一个能让你得到你想要的东西的主意。如果这需要一点理解的话,请原谅我,但我希望您看到,这实际上是一个相当简单的解决中度复杂问题的方法。
我会将查询(在PHP中)构建为有n个自联接,其中n是作业所需的时隙数。自联接将加入下一个连续时隙,并根据所有时隙中可用的资源对结果进行细化。注意,您可以将动态创建的WHERE子句移到联接条件中.我已经看到了MySQL的版本,它将以这种方式提高速度。
php代码:
// $r1, $r3, and $r3 are the required resources for this job.
$join_format = 'JOIN timeslots AS %s ON %date = %s.date AND %s.timeslot+1 = %s.timeslot';
$where_format = '(%s.r1 >= '.$r1.' AND %s.r2 >= '.$r2.' AND %s.r3 >= '.$r3.')';
$joins = array();
$wheres = array("block1.date > CURDATE()",
sprintf($where_format, "block1", "block1", "block1")
);
$select_list = 'block1.date, block1.timeslot as starting_time, block' . $slots_needed . '.timeslot as ending_time';
for($block = 2; $block <= $slots_needed; $block++) {
$join_alias = "block" . $block;
$previous_alias = "block" . ($block-1);
$joins[] = sprintf($join_format, $join_alias, $previous_alias,$join_alias, $previous_alias, $join_alias);
$wheres[] = sprintf($where_format, $join_alias, $join_alias, $join_alias);
}
$query_format = 'SELECT %s FROM timeslots as block1 %s WHERE %s GROUP BY block1.date, block1.timeslot ORDER BY block1.date ASC, block1.timeslot ASC';
$joins_string = implode(' ', $joins);
$wheres_string = implode(' AND ', $wheres);
$query = sprintf($query_format, $select_list, $joins_string, $wheres_string);就我的意图而言,这应该会产生这样的查询(对于两个需要的块,每个块需要一个所需的资源:
结果SQL:
SELECT
block1.date,
block1.timeslot as starting_time,
block2.timeslot as ending_time
FROM
timeslots AS block1
JOIN timeslots AS block2
ON block1.date = block2.date AND block1.timeslot+1 = block2.timeslot
WHERE
block1.date > CURDATE()
AND (block1.r1 >= 1 AND block1.r2 >= 1 AND block1.r3 >= 1)
AND (block2.r1 >= 1 AND block2.r2 >= 1 AND block2.r3 >= 1)
GROUP BY
block1.date, block1.timeslot
ORDER BY
block1.date ASC, block1.timeslot ASC它应产生以下结果:
预期结果集:
+------------+---------------+-------------+
| date | starting_time | ending_time |
+------------+---------------+-------------+
| 2001-01-01 | 1 | 2 |
+------------+---------------+-------------+
| 2001-01-01 | 2 | 3 |
+------------+---------------+-------------+
| 2001-01-01 | 7 | 8 |
+------------+---------------+-------------+
| 2001-01-01 | 8 | 9 |
+------------+---------------+-------------+
| 2001-01-02 | 4 | 5 |
+------------+---------------+-------------+注意,如果需要2个块,但有3个可用(连续),则查询将返回两个选项(第一次和第二次或第二次和第三次可用)。
https://stackoverflow.com/questions/11424029
复制相似问题