PostgreSQLにいくつかのデータを含むテーブルがあります。
create table t2 (
key jsonb,
value jsonb
);
INSERT INTO t2(key, value)
VALUES
('1', '"test 1"')
,('2', '"test 2"')
,('3', '"test 3"')
,('[]', '"test 4"')
,('[1]', '"test 5"')
,('[2]', '"test 6"')
,('[3]', '"test 7"')
,('[1, 2]', '"test 8"')
,('[1, 2, 3]', '"test 9"')
,('[1, 3]', '"test 10"')
,('[1,2,4]', '"test 11"')
,('[1, 2,4]', '"test 12"')
,('[1,3,13]', '"test 13"')
,('[1, 2, 15]', '"test 15"');
そして、私はこれらの行をそのようにソートしようとします:
SELECT key FROM t2 order by key;
結果は次のとおりです。
[]
1
2
3
[1]
[2] <==
[3] <==
[1, 2]
[1, 3] <==
[1, 2, 3]
[1, 2, 4]
[1, 2, 4]
[1, 2, 15]
[1, 3, 13]
しかし、私が必要なのは:
[]
1
2
3
[1]
[1, 2]
[1, 2, 3]
[1, 2, 4]
[1, 2, 4]
[1, 2, 15]
[1, 3] <==
[1, 3, 13]
[2] <==
[3] <==
それを達成する方法はありますか?
まず、質問と列名_"key"
_は誤解を招く可能性があります。列キーには、JSONkeysは含まれず、valuesのみが含まれます。それ以外の場合は、関数jsonb_object_keys(jsonb)
を使用してキーを抽出できますが、そうではありません。
すべてのJSON配列が空であるか、または示されているように整数を保持していると仮定します。また、スカラー値(非配列)も整数です。
基本的な並べ替え順序はPostgres integer
(またはnumeric
)配列で機能します。私はこの小さなヘルパー関数を使用して、jsonb
配列をPostgres _int[]
_に変換します。
_CREATE OR REPLACE FUNCTION jsonb_arr2int_arr(_js jsonb)
RETURNS int[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT j::int FROM jsonb_array_elements_text(_js) j)';
_
説明:
次に jsonb_typeof(jsonb)
を追加して、以下に到達します。
_SELECT key
FROM t2
ORDER BY key <> '[]' -- special case for empty array
, jsonb_typeof(key) DESC -- 'number' before 'array'
, CASE jsonb_typeof(key) -- sort arrays as converted int[]
WHEN 'array' THEN jsonb_arr2int_arr(key)
WHEN 'number' THEN ARRAY[key::text::int]
END;
_
目的の結果を正確に生成します。
btree
データムのjsonb
順序付けは、あまり関心の対象となることはめったにありませんが、完全にするために次のようにします。_
Object > Array > Boolean > Number > String > Null
_
_Object with n pairs > object with n - 1 pairs
_
_Array with n elements > array with n - 1 elements
_ペアの数が等しいオブジェクトは、次の順序で比較されます。
_key-1, value-1, key-2 ...
_オブジェクトキーは格納順に比較されることに注意してください。特に、短いキーは長いキーの前に保存されるため、次のような直感的でない結果になる可能性があります。
_{ "aa": 1, "c": 1} > {"b": 1, "d": 1}
_同様に、要素数が等しい配列は次の順序で比較されます。
_element-1, element-2 ...
_
大胆な強調鉱山。
それが_jsonb '[2]' < jsonb '[1, 2]'
_です。
しかし、Postgres配列は要素ごとにソートするだけです:_'{2}'::int[] > '{1, 2}'
_-まさにあなたが探していたものです。
問題を参照して、json整数値で結果を並べ替えます。試してください:
select myjson from mytable order by (myjson->>'some_int')::int;
あなたの場合、それは順序付けキーの配列のようです。したがって、最初に「キー」フィールドの値を連結してみてください。