首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >选择下n行满足条件的行

选择下n行满足条件的行
EN

Stack Overflow用户
提问于 2012-07-11 00:48:01
回答 1查看 280关注 0票数 3

假设我们有这个资源可用性表:

代码语言:javascript
复制
+-----------+-----------------------------------------------------------+
| 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。假设任务需要一个时隙,我可以使用以下查询:

代码语言:javascript
复制
SELECT `date`, `timeslot` FROM `resource_availability` 
WHERE
  `r1` > '1' AND
  `r2` > '0' AND
  `r3` > '2'
ORDER BY 'date`, `timeslot`;

但是,如果我有另一个作业,job #86需要3次才能完成,并且无法停止-重新启动,那么是否有可能通过查询获得安全的启动时间?

我目前正在检查我的while循环中的连续性,但我认为可以让查询这样做。

如果可能的话,我想知道哪一个更快、更有效率。为了进行效能评估,应该注意的是,此表作为一种位图经常被更新--也就是说,在每一项作业被调度时,资源可用性列都会被更新。

而且,很明显,这个系统的目的是允许检查什么-ifs。如果我的方法不是最优的,还有什么更好的选择吗?

如果最后一个问题太多,请忽略它,或者在评论中让我知道,我会删除它。

EN

回答 1

Stack Overflow用户

发布于 2012-07-11 05:13:14

呜呜..。我想出了一个能让你得到你想要的东西的主意。如果这需要一点理解的话,请原谅我,但我希望您看到,这实际上是一个相当简单的解决中度复杂问题的方法。

我会将查询(在PHP中)构建为有n个自联接,其中n是作业所需的时隙数。自联接将加入下一个连续时隙,并根据所有时隙中可用的资源对结果进行细化。注意,您可以将动态创建的WHERE子句移到联接条件中.我已经看到了MySQL的版本,它将以这种方式提高速度。

php代码:

代码语言:javascript
复制
// $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:

代码语言:javascript
复制
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

它应产生以下结果:

预期结果集:

代码语言:javascript
复制
+------------+---------------+-------------+
|    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个可用(连续),则查询将返回两个选项(第一次和第二次或第二次和第三次可用)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11424029

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档