如何解决有postgres CLOSEST运算子吗?
| 我正在寻找某种东西,给定一个像这样的表:| id | number |
| 1 | .7 |
| 2 | 1.25 |
| 3 | 1.01 |
| 4 | 3.0 |
查询SELECT * FROM my_table WHERE
numberCLOSEST(1)
将返回第3行。我只关心数字。现在,我有一个过程可以遍历每一行并进行比较,但是我认为该信息应该可以从b树索引中获取,因此这可能是内置的,但我不能查找任何表明这样做的文档。
解决方法
我可能对语法不太满意,但是此参数化查询(所有?取原始问题的\'1 \')应该运行很快,基本上是2个B-Tree查找[假定索引编号]。
SELECT * FROM
(
(SELECT id,number FROM t WHERE number >= ? ORDER BY number LIMIT 1) AS above
UNION ALL
(SELECT id,number FROM t WHERE number < ? ORDER BY number DESC LIMIT 1) as below
)
ORDER BY abs(?-number) LIMIT 1;
具有〜5e5行的表(索引在number
上)的查询计划如下所示:
psql => explain select * from (
(SELECT id,number FROM t WHERE number >= 1 order by number limit 1)
union all
(select id,number from t where number < 1 order by number desc limit 1)
) as make_postgresql_happy
order by abs (1 - number)
limit 1;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Limit (cost=0.24..0.24 rows=1 width=12)
-> Sort (cost=0.24..0.24 rows=2 width=12)
Sort Key: (abs((1::double precision - public.t.number)))
-> Result (cost=0.00..0.23 rows=2 width=12)
-> Append (cost=0.00..0.22 rows=2 width=12)
-> Limit (cost=0.00..0.06 rows=1 width=12)
-> Index Scan using idx_t on t (cost=0.00..15046.74 rows=255683 width=12)
Index Cond: (number >= 1::double precision)
-> Limit (cost=0.00..0.14 rows=1 width=12)
-> Index Scan Backward using idx_t on t (cost=0.00..9053.67 rows=66136 width=12)
Index Cond: (number < 1::double precision)
(11 rows)
,您可以尝试这样的事情:
select *
from my_table
where abs(1 - number) = (select min(abs(1 - number)) from t)
与手动循环遍历表没有太大区别,但至少它可以让数据库在“数据库空间”内部进行循环,而不必在函数和数据库内部之间来回跳转。另外,将其全部推送到单个查询中可以使查询引擎知道您要执行的操作,然后可以尝试以一种明智的方式进行操作。
,第二个答案是正确的,但是我在\“ UNION ALL \”上遇到错误:
DBD::Pg::st execute failed: ERROR: syntax error at or near \"UNION\"
我用以下代码修复了它:
SELECT * FROM
(
(SELECT * FROM table WHERE num >= ? ORDER BY num LIMIT 1)
UNION ALL
(SELECT * FROM table WHERE num < ? ORDER BY num DESC LIMIT 1)
) as foo
ORDER BY abs(?-num) LIMIT 1;
诀窍是从内部表中删除AS,并仅在UNION上使用它。
,如果您希望在组内找到最接近的值,则此代码很有用。在这里,我根据列val
接近目标值0.5的接近程度将表tb
除以column_you_wish_to_group_by
。
SELECT *
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY t.column_you_wish_to_group_by ORDER BY abs(t.val - 0.5) ASC) AS r,t.*
FROM
tb t) x
WHERE x.r = 1;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。