Jsonオブジェクトのスライス内の最大値を取得したい(通常[1,2,3,5,6,7,9,10]
)テーブルData
のraw
というフィールドに含まれています。
スライスの制限Start
&End
は、Features
という名前のテーブルに含まれるfeatures
という名前の他のJsonオブジェクトに含まれています
ここに入力があります:
CREATE TABLE raw (
id int PRIMARY KEY
GENERATED BY DEFAULT AS IDENTITY
data json
);
INSERT INTO raw (data) VALUES
('[1,2,3,5,6,7,9,10]');
CREATE TABLE features (
id int,
features json
);
INSERT INTO features (id, features) VALUES
(1, '{"Start" : 1, "End": 5}');
私が望む出力は7
、つまりスライスの最大値[2,3,5,6,7]
これは私が他の投稿を見て思いついたものですが、うまくいきません...
SELECT
R."ID",
F."Features"->>'Start' AS Start,
F."Features"->>'End' AS End,
sort_desc((array(select json_array_elements(R."Data")))[F."Features"->>'Start':F."Features"->>'End'])[1] as maxData
FROM
raw AS R
INNER JOIN
features AS F ON R."ID" = F."ID"
表示されるおおよそのエラーメッセージはsort_desc
:
この名前またはこのタイプの引数に対応する関数はありません。データのタイプを変換する必要があります
Json配列のネストを解除できます:
Postgres WITH ORDINALITY :
FROM句の関数の末尾にWITH ORDINALITYを付けると、bigint列が出力に追加されます。この列は、1から始まり、関数の出力の行ごとに1ずつ増加します。これは、unnest()などのセットを返す関数の場合に最も役立ちます。
Erwin Brandstetter のこの答えを見てください:
SELECT
r."ID",
MAX(t.elem::int) MaxElem
FROM
raw r
JOIN
features f
ON f."ID" = r."ID"
JOIN LATERAL
json_array_elements_text(r."Data")
WITH ORDINALITY AS t(elem, n) ON TRUE
WHERE
n >= (f."Features"->>'Start')::int + 1
AND
n <= (f."Features"->>'End')::int + 1
GROUP BY
r."ID";
ID | maxelem -:| ------: 1 | 7
db <> fiddle ここ
または、intarrayモジュールを使用する場合:
SELECT
r."ID",
(sort_desc(((ARRAY(SELECT json_array_elements_text(r."Data")))::int[])[(f."Features"->>'Start')::int + 1:(f."Features"->>'End')::int + 1]))[1]
FROM
raw r
JOIN
features f
ON f."ID" = r."ID";
rextester ここ
これは恐ろしいスキーマの周りです。 (実際には)json
を(jsonb
と比較して)まったく使用しないでください。フィールドでクエリを実行する場合は、jsonb
にする必要があります。あなたの場合、それはまだ悪い考えですが、おそらくSQL配列が必要です。
CREATE TABLE raw (
raw_id int PRIMARY KEY
GENERATED BY DEFAULT AS IDENTITY,
data int[]
);
INSERT INTO raw (data) VALUES ('{1,2,3,5,6,7,9,10}');
CREATE TABLE features (
feature_id int REFERENCES raw,
low smallint,
high smallint
);
INSERT INTO features ( feature_id, low, high ) VALUES ( 1, 1, 5 );
これで、次のようにクエリできますsqlは1ベースであることを覚えておいてください、
SELECT max(unnest)
FROM raw
CROSS JOIN features AS f
CROSS JOIN LATERAL unnest(data[f.low:f.high]);
上記を最適化するため、intarray
モジュールも確認してください。
CREATE EXTENSION intarray;
SELECT max(unnest)
FROM raw
CROSS JOIN features AS f
CROSS JOIN LATERAL unnest(subarray(data,f.low,f.high-f.low+1))
配列の最後の要素だけが必要な場合は、これをさらに最適化できます。
これがGISの問題である場合は、おそらく間違っている可能性がありますが、少なくともこの方法は正気です