我擁有數百萬個多邊形,以及一個更大的柵格(平鋪)表。我想要st_clip(光柵,多邊形),然後在裁剪的光柵上應用st_summarystatsagg()。代碼如下所示。捕獲postgis st_clip的錯誤,並修復「無法從工作柵格獲得帶子」
with pieces as (
select d.pid,
st_clip(r.rast, d.geom) as rast
from tbl_raster as r
inner join tbl_poly as d
on st_intersects(r.rast, d.geom)
)
insert into tbl_out(pid, val1, val2, val3)
select pid,
(stats1).mean as v1,
(stats2).mean as v2,
(stats3).mean as v3
from (
select p.pid,
st_summarystatsagg(p.rast, 1, true) as stats1,
st_summarystatsagg(p.rast, 2, true) as stats2,
st_summarystatsagg(p.rast, 3, true) as stats3
from pieces as p
group by p.pid
);
代碼工作的多邊形(千)的小部分,但是當我通過數以百萬計,它回來了錯誤
ERROR: RASTER_clip: Could not get band from working raster
CONTEXT: PL/pgSQL function st_clip(raster,integer[],geometry,double precision[],boolean) line 8 at RETURN
我要得到什麼多邊形的多個診斷消息引起這樣的麻煩。有沒有辦法做try-catch塊類型的東西,然後我要從那裏轉儲一些信息。或者讓它給一些空值或什麼,並使查詢完成,然後我看問題的輸出。
postgresql的版本是9.6.1,postgis是2.3.1,gdal 2.1.2,並使用psql -f
在Linux上運行。
謝謝!
編輯:
繼@ Eelke的建議下,我用PL/pgSQL的環路,並確定問題的所在。
似乎如果多邊形接觸沒有共享內部點的柵格,ST_Clip會失敗,如果有多個頻段計算請求。如下面的測試代碼所示,如果我計算ST_與多邊形交互的柵格聯合,它似乎按預期工作(由我)。但結果是代價很高。我希望找到ST_Intersects的替代方法,如果沒有共享內部點,它不會選擇。但我找不到一個功能來做到這一點,無法找出表情......有沒有這種表情?
下面是我想出了一個可重複的結果:
--DROP SCHEMA IF EXISTS test_rast;
--CREATE SCHEMA test_rast;
SET search_path TO test_rast, public;
-- Create raster catalog of 3 bands
DROP TABLE IF EXISTS dummy_rast_3band;
CREATE TABLE dummy_rast_3band(rid int, rast raster);
INSERT INTO dummy_rast_3band(rid, rast)
VALUES
(1, ST_AddBand(
ST_MakeEmptyRaster(240, 240, 82, 59.6, 6./3600., 6./3600., 0, 0, 4326),
ARRAY[
ROW(1, '8BUI'::text, 0, 255),
ROW(2, '8BUI'::text, 0, 255),
ROW(3, '8BUI'::text, 0, 255)
]::addbandarg[]
)
),
(2, ST_AddBand(
ST_MakeEmptyRaster(240, 240, 82.4, 59.6, 6./3600., 6./3600., 0, 0, 4326),
ARRAY[
ROW(1, '8BUI'::text, 0, 255),
ROW(2, '8BUI'::text, 0, 255),
ROW(3, '8BUI'::text, 0, 255)
]::addbandarg[]
)
) ;
-- Almost identical raster catalogue, the only difference being there is only one band
DROP TABLE IF EXISTS dummy_rast_1band;
CREATE TABLE dummy_rast_1band(rid int, rast raster);
INSERT INTO dummy_rast_1band(rid, rast)
VALUES
(1, ST_AddBand(
ST_MakeEmptyRaster(240, 240, 82, 59.6, 6./3600., 6./3600., 0, 0, 4326),
'8BUI'::text, 0, NULL
)
),
(2, ST_AddBand(
ST_MakeEmptyRaster(240, 240, 82.4, 59.6, 6./3600., 6./3600., 0, 0, 4326),
'8BUI'::text, 0, NULL
)
) ;
-- Prepare polygon which touches one raster
DROP TABLE IF EXISTS dummy_poly;
CREATE TABLE dummy_poly(pid int, geom geometry);
INSERT INTO dummy_poly(pid, geom)
VALUES
(1, ST_GeomFromText('MULTIPOLYGON(((82.4180000000001 59.8655000000001,82.4 59.8655000000001,82.4 59.8745000000001,82.4180000000001 59.8745000000001,82.4180000000001 59.8655000000001)))', 4326));
-- Four tests with ST_Clip()
-- This works, with 1-band raster
SELECT ST_Summary(ST_Clip(r.rast, d.geom))
FROM dummy_rast_1band AS r INNER JOIN dummy_poly AS d
ON ST_Intersects(r.rast, d.geom);
-- This fails with
-- RASTER_clip: Could not get band from working raster
-- CONTEXT: PL/pgSQL function st_clip(raster,integer[],geometry,double precision[],boolean)
-- line 8 at RETURN
SELECT ST_Summary(ST_Clip(r.rast, d.geom))
FROM dummy_rast_3band AS r INNER JOIN dummy_poly AS d
ON ST_Intersects(r.rast, d.geom);
-- If ask for one band, that works
SELECT ST_Summary(ST_Clip(r.rast, 2, d.geom, true))
FROM dummy_rast_3band AS r INNER JOIN dummy_poly AS d
ON ST_Intersects(r.rast, d.geom);
-- If I union raster into bigger piece, it works
SELECT ST_Summary(ST_Clip(ST_Union(r.rast), d.geom))
FROM dummy_rast_3band AS r INNER JOIN dummy_poly AS d
ON ST_Intersects(r.rast, d.geom)
GROUP BY d.geom;
我認爲,如果您要編寫一個pgsql函數來檢索數據並逐行處理它,您可以捕獲錯誤並報告發生在哪一行上。 – Eelke
謝謝你的建議,這似乎是一個好主意。 – yosukesabai