【发布时间】:2015-04-15 19:42:25
【问题描述】:
我在执行以下操作时遇到了一些问题:我有一个名为 entries 的数据库表(出于所有意图和目的),除了主键之外还有 3 列:value、gps_lat、gps_long all其中是双打。
我的最终目标是能够定义一个网格,比如 100x100 的间隔,并以给定的纬度和经度值为界,对于网格的每个正方形,我想计算该网格中所有点的平均值正方形。但是,我在有效地执行此操作时遇到了很多麻烦。
部分问题是我想将其设置为存储过程或查询,我可以使用一段代码生成并在以后重用,因为每次运行查询时,网格都不相同(所以缓存几乎是不可能的)。
我第一次尝试这样做是定义以下函数:
CREATE OR REPLACE FUNCTION gridSquareAverageValue (double precision
, double precision, double precision, double precision)
RETURNS double precision as $avgValue$
declare
avgValue double precision;
BEGIN
SELECT AVG(value) into avgValue FROM entries
WHERE gps_lat BETWEEN $1 AND $2 AND gps_long BETWEEN $3 AND $4;
RETURN avgValue;
END;
$avgValue$ LANGUAGE plpgsql;
这个函数工作得很好,完全符合我的需要,除了它只对一个方格进行。为 100x100 网格运行该函数涉及 10,000 个单独的查询,因此速度非常慢。
下一次尝试是这样的:
WITH Grid(lat_offset,long_offset) AS
(SELECT *
FROM generate_series(1,10) lat_offset
CROSS JOIN generate_series(1,10) long_offset)
SELECT AVG(value)
FROM Grid
JOIN entries
ON entries.gps_lat BETWEEN 41.79604807005128 + (0.000247908106797 * Grid.lat_offset)
AND 41.82083888073101 + (0.002479081067973 * (Grid.lat_offset + 1))
AND entries.gps_long BETWEEN -72.2759199142456 + (0.000527858734131 * Grid.long_offset)
AND -72.22313404083252 + (0.005278587341308 * (Grid.long_offset + 1))
GROUP BY lat_offset,long_offset;
不知何故,结果变得更糟了。我尝试生成一系列偏移量,然后将其与条目表连接起来,强制每个条目进入一个使用您可以在上面看到的数学计算的框中。这是不可能的慢。我试图让它只输出值而不计算平均值,它比运行 10k 个单独的查询花费的时间更长。
上述方法也可能是最有前途的方法,因为在生成两个系列的笛卡尔连接后,我真正想做的就是在一个简单的函数中使用它们,但除了你的方法之外,我想不出任何体面的方法来做到这一点见上文 =/
最后我尝试了这个:
# $1 height $2 width $3 lat start $4 lat interval $5 long start $6 long interval
CREATE OR REPLACE FUNCTION gridAverageValue (integer, integer, double precision, double precision, double precision, double precision)
RETURNS TABLE (avg double precision) as $restbl$
BEGIN
SELECT * INTO $restbl$ FROM entries WHERE 1 = 2;
FOR lat_offset IN 0..$1 LOOP
FOR long_offset IN 0..$2 LOOP
INSERT INTO restbl
SELECT AVG(value)
FROM entries
WHERE gps_lat
BETWEEN $3 + ($4 * lat_offset) AND $3 + ($4 * (lat_offset + 1))
AND gps_long
BETWEEN $5 + ($6 * long_offset) AND $5 + ($6 * (long_offset + 1));
END LOOP;
END LOOP;
RETURN QUERY SELECT * FROM restbl;
END;
$restbl$ LANGUAGE plpgsql;
最后一次尝试遇到了一堆语法错误,老实说,我不知道它来自哪里。总体思路是生成一堆查询,最终计算出我关心的值。
如果有人对如何解决上述任何方法有任何建议,将不胜感激。
【问题讨论】:
-
请提供您的 Postgres 版本。
-
关于您上一个函数的失败尝试:您似乎误解了美元报价:stackoverflow.com/questions/12144284/…
标签: sql postgresql stored-procedures gps aggregate-functions