配列を含むjsonbキーの並べ替え順序をカスタマイズする


9

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] <==

それを達成する方法はありますか?


だからここにあなたの答えはありますか?
Erwin Brandstetter

回答:


8

まず、質問と列名"key"は誤解を招くものです。列キーにはJSON キーは含まれず、のみが含まれます。それ以外の場合は、関数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;

希望する結果を正確に生成します。

どうして?

マニュアルはjsonb説明します:

データムの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}'です。


0

問題を参照して、json整数値で結果を並べ替えます。試してください:

select myjson from mytable order by (myjson->>'some_int')::int;

あなたの場合、それは注文キーの配列のようです。したがって、最初に「キー」フィールドの値を連結してみてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.