배열과 관련된 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.