我有一个设定的数值范围,我想优化。
下面是一个简单的初始值示例:
Start End
9 12
1 2
60 88
10 11
79 80
我期望优化后的输出:
Start End
1 2
9 12
60 88
这些是存储在left
数据库中的修改前顺序树遍历(嵌套集)数据中的MySQL和right
值。我使用它们从结果中排除不活动的分支,并且目前根本没有优化范围。我想我可能会从优化使用前的范围中获得性能上的提高。
更多信息
使用NOT BETWEEN
子句将这些值传递到查询中,以排除树中的非活动分支。我认为可以通过使用最小范围集来优化该查询的性能。
发布于 2011-04-07 08:05:29
下面是一个SQL,它将返回您想要的
mysql> CREATE TABLE sample (Start INT, End INT);
mysql> INSERT sample VALUES (9,12),(1,2),(60,88),(10,11),(79,80);
mysql> SELECT *
-> FROM sample s
-> WHERE NOT EXISTS (SELECT 1
-> FROM sample
-> WHERE s.Start > Start AND s.Start < End);
+-------+------+
| Start | End |
+-------+------+
| 9 | 12 |
| 1 | 2 |
| 60 | 88 |
+-------+------+
当然,您可以使用上面的SQL创建视图、将数据移动到另一个表或删除行。
注意:我不太清楚你为什么要做这个‘优化’。
编辑:
查询可以重写为
SELECT s.*
FROM sample s LEFT JOIN
sample s2 ON s.Start > s2.Start AND s.Start < s2.End
WHERE s2.start IS NULL;
这将创建不同的执行计划(2xSimpleSelectvs主/依赖子查询的存在),因此性能可能有所不同。如果存在索引,这两个查询都将在(开始、结束)上使用索引。
发布于 2011-04-06 14:16:29
把它们放在一个排序的列表中。标记排序列表中的哪些元素表示范围开始,哪些表示范围结束。首先根据值对列表进行排序;但是,确保范围在范围结束之前就开始了。(这可能涉及某种可以在给定密钥上排序的结构。我不知道php中的细节。)
现在,从头到尾遍历列表。留个柜台,c
。当您通过范围开始时,增量c
。当您通过范围结束时,减少c
。
当c
从0到1时,这是最后一组范围的开始。当c
从1到0时,这就是范围的结束。
编辑::如果您已经在某个数据库表中有了范围,您可能可以构造一个SQL查询来执行上面的第一步(同样,确保在范围结束点之前返回范围起始点)。
发布于 2011-04-06 14:22:42
下面是一个简单的实现:
// I picked this format because it's convenient for the solution
// and because it's very natural for a human to read/write
$ranges = array(
9 => 12,
1 => 2,
60 => 81,
10 => 11,
79 => 88);
ksort($ranges);
$count = count($ranges);
$prev = null; // holds the previous start-end pair
foreach($ranges as $start => $end) {
// If this range overlaps or is adjacent to the previous one
if ($prev !== null && $start <= $prev[1] + 1) {
// Update the previous one (both in $prev and in $ranges)
// to the union of its previous value and the current range
$ranges[$prev[0]] = $prev[1] = max($end, $prev[1]);
// Mark the current range as "deleted"
$ranges[$start] = null;
continue;
}
$prev = array($start, $end);
}
// Filter all "deleted" ranges out
$ranges = array_filter($ranges);
限制/说明:
int
。0
,则此示例将错误地从最终结果中删除任何范围。如果您的数据能够合法地包含这样的范围,则提供对array_filter
:function($item) { return $item === null; }
的适当回调。看到它的行动。
https://stackoverflow.com/questions/5567621
复制相似问题