我有一个MySQL数据库,其中包含数字范围。它具有以下结构:
range_id,start,end
所有列都是INT(10)。此外,还有一个名为range_poly的Polygon字段用于索引。
我想标记所有'外部'范围:数据库中另一个范围内未包含的所有范围。例如:
range_id | start | end
1 | 1 | 2
2 | 4 | 5
3 | 1 | 10
在这种情况下,第三个记录是'外部范围',因为它不包含在另一个范围内,但第一个和第二个记录不是因为它们完全包含在记录3中。为了实现这一目的,我添加了一个列名为is_outer,它是一个简单的INT(1),用于指示范围是否包含在另一个范围内。我使用以下PHP脚本:
$result = mysql_query(mysql_real_escape_string("SELECT range_id, start FROM table;"), $db);
while($row = mysql_fetch_array($result))
{
$result2 = mysql_query(mysql_real_escape_string("SELECT range_id FROM table WHERE MBRCONTAINS( range_poly, POINTFROMWKB( POINT( ". $row['start'] ." , 0 ) ) ) ORDER BY (`end` - `start`) DESC LIMIT 1;"), $db);
$row2 = mysql_fetch_array($result2);
mysql_query(mysql_real_escape_string("UPDATE table SET is_outer = 1 WHERE range_id = ". $row2['range_id'] . ";"), $db);
}
这很好但我不禁觉得应该有一个更简单的方法来实现这一目标。我似乎无法将我的大脑包裹起来,这是基于纯SET的查询。或者我可以使用CURSOR对此进行编码,但我想知道与PHP版本相比,性能是否会更好。我的数据库有大约370万条记录,这解释了为什么性能非常重要。
我尝试使用子查询但子查询中不允许使用LIMIT。另外,我正在考虑加入桌子,但我无法绕过正确的条件。
答案 0 :(得分:0)
如果我正确理解你的问题,你想要归还所有父母(外部范围)。
如果是这样,请尝试以下方法:
SELECT
t1.range_id
FROM YourTable t1
LEFT JOIN YourTable t2 ON
t1.start >= t2.start AND t1.end <= t2.end AND t1.range_id <> t2.range_id
WHERE t2.range_id IS NULL
这是SQL Fiddle。
如果您有重复数据(7,33,36)和(8,33,36),并且您希望两者都返回,则可以将其添加到WHERE子句中:
OR (t1.start = t2.start AND t1.end = t2.end)
祝你好运。