我有SQLite数据库,我在其中有一些类型为"double"的列.我想获得一个在此列值中最接近指定值的行.
例如,在我的表中我有:
id: 1; value: 47 id: 2; value: 56 id: 3; value: 51
我想得到一个其值最接近50的行.所以我想收到id:3(value = 51).
我怎样才能实现这个目标?
谢谢.
这应该工作:
SELECT * FROM table ORDER BY ABS(? - value) LIMIT 1
Where ?
代表您要比较的值.
使用order-by,SQLite将扫描整个表并将所有值加载到临时b树中以对它们进行排序,从而使任何索引无效.这将非常慢并且在大型表上使用大量内存:
explain query plan select * from 'table' order by abs(10 - value) limit 1; 0|0|0|SCAN TABLE table 0|0|0|USE TEMP B-TREE FOR ORDER BY
您可以使用索引获得下一个更低或更高的值,如下所示:
select min(value) from 'table' where x >= N; select max(value) from 'table' where x <= N;
您可以使用union
从单个查询中获取两者:
explain query plan select min(value) from 'table' where value >= 10 union select max(value) from 'table' where value <= 10; 1|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value>?) 2|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value) 0|0|0|COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)
即使在大型桌子上,这也会非常快.您可以简单地加载这两个值并在代码中对它们进行评估,或者使用更多的sql以各种方式选择一个:
explain query plan select v from ( select min(value) as v from 'table' where value >= 10 union select max(value) as v from 'table' where value <= 10) order by abs(10-v) limit 1; 2|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value>?) 3|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value) 1|0|0|COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION) 0|0|0|SCAN SUBQUERY 1 0|0|0|USE TEMP B-TREE FOR ORDER BY
要么
explain query plan select 10+v from ( select min(value)-10 as v from 'table' where value >= 10 union select max(value)-10 as v from 'table' where value <= 10) group by v having max(abs(v)) limit 1; 2|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value>?) 3|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value) 1|0|0|COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION) 0|0|0|SCAN SUBQUERY 1 0|0|0|USE TEMP B-TREE FOR GROUP BY
由于您对任意大于和小于目标的值感兴趣,因此您无法避免进行两次索引搜索.但是,如果你知道目标在一个小范围内,你可以使用"between"来只触及一次索引:
explain query plan select * from 'table' where value between 9 and 11 order by abs(10-value) limit 1; 0|0|0|SEARCH TABLE table USING COVERING INDEX value_index (value>? AND value) 0|0|0|USE TEMP B-TREE FOR ORDER BY
当它仅评估1-2个值时,这将比上面的联合查询快2倍,但如果您开始加载更多数据,它将很快变慢.