Postgres가 어레이에 없습니다.


98

Postgres의 기본 배열 유형을 사용하고 있으며 ID가 배열 수신자 ID에없는 레코드를 찾으려고합니다.

그들이 어디에 있는지 찾을 수 있습니다.

SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))

그러나 이것은 작동하지 않습니다.

SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3  = NOT ANY (recipient_ids))

이 상태를 테스트하는 올바른 방법은 무엇입니까?


않는 WHERE 3 NOT IN recipient_ids일을?
Janus Troelsen 2012

1
관련 메모 : text[]int[]어레이 :select not(array[1,2,3] @> array[3]);
Steve Peak

3
전문가 팁 : null열이 배열에 포함되어 있는지 여부를 확인하는 경우 항상 아니요라고 표시됩니다. 그것은 널 (null)이 배열에 포함되는 경우 확인할 수 없다는 결론에 도달하기 위해 몇 가지 포함하는 방법을 디버깅 20분 같은 날 데려 갔어
앙드레 페냐에게

답변:


138
SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))

당신은 항상 부정 할 수 WHERE (condition)와 함께WHERE NOT (condition)


2
@aschyiel - 당신은로 다시 전환 할 수 있습니다 ANY대신에 IN당신과 같이 recipient_ids입력리스트가 성장 : stackoverflow.com/questions/1009706/...
derekm

41

약간 돌려서 "3은 모든 ID와 같지 않습니다"라고 말할 수 있습니다.

where 3 != all (recipient_ids)

로부터 미세 설명서 :

9.21.4. ALL (배열)

expression operator ALL (array expression)

오른쪽은 괄호로 묶인 표현식으로 배열 값을 산출해야합니다. 왼쪽 표현식은 지정된 operator를 사용하여 배열의 각 요소와 비교되고 평가되며 , 이는 부울 결과를 산출해야합니다. ALL모든 비교 결과 가 true이면 결과 는 "true"입니다 (배열에 요소가없는 경우 포함). 거짓 결과가 발견되면 결과는 "거짓"입니다.


이건 정말 이유를 설명하지 않습니다 any이 경우 작동하지 않습니다
seanlinsley

이유를 제대로 설명했기 때문에 받아 들여 져야합니다. PS 당신은 찾을 수 anyall말한다 포스트 그레스 문서에 " x <> ANY (a,b,c) 에 해당합니다 x <> a OR <> b OR x <> c." ref : postgresqltutorial.com/postgresql-any postgresqltutorial.com/postgresql-all
Tyler Temp

19

ALL/ANY답변 증대

나는 결과 를 사용 all하거나 any달성하기 위해 모든 솔루션을 선호하며 , 추가 메모 (예 : NULL 에 대한)를 높이 평가합니다 . 또 다른 확대로서, 여기에 이러한 연산자에 대해 생각하는 방법이 있습니다.

단락 연산자 로 생각할 수 있습니다 .

  • all(array)배열의 모든 값을 살펴보고 제공된 연산자를 사용하여 각각을 참조 값과 비교합니다. 비교 결과가 산출 되 자마자 false프로세스는 거짓으로 끝나고 그렇지 않으면 참으로 끝납니다. (논리적 단락과 비교 and)
  • any(array)배열의 모든 값을 살펴보고 제공된 연산자를 사용하여 각각을 참조 값과 비교합니다. 비교 결과가 true나 오자마자 프로세스는 true로 끝나고 그렇지 않으면 false로 끝납니다. (논리적 단락과 비교 or)

이것이 3 <> any('{1,2,3}')원하는 결과를 얻지 못하는 이유입니다 . 프로세스는 부등식에 대해 3과 1을 비교하여 참이고 즉시 참을 반환합니다. 3과 다른 배열의 단일 값은 전체 조건을 참으로 만들기에 충분합니다. 마지막 배열 위치의 3은 prob입니다. 사용하지 않았습니다.

3 <> all('{1,2,3}')반면에 모든 값이 같지 않은지 확인 합니다. 3. 전체 결과로 false를 반환하기 위해 false를 생성하는 요소 (이 경우 마지막)까지 true를 생성하는 모든 비교를 실행합니다. 이것이 OP가 원하는 것입니다.



12

업데이트:

postgres 9.3부터,

이 작업 을 수행하기 위해 (포함 연산자)NOT 와 함께 사용할 수도 있습니다 .@>

IE.

SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];


12

NULL주의

둘 다 ALL:

(some_value != ALL(some_array))

그리고 ANY:

NOT (some_value = ANY(some_array))

some_arraynull이 아닌 한 작동 합니다. 배열이 null 일 수있는 경우 coalesce ()로 설명해야합니다. 예 :

(some_value != ALL(coalesce(some_array, array[]::int[])))

또는

NOT (some_value = ANY(coalesce(some_array, array[]::int[])))

로부터 문서 :

배열 표현식이 널 배열을 생성하면 ANY의 결과는 널이됩니다.

배열 표현식이 널 배열을 생성하면 ALL의 결과는 널이됩니다.


3

ANY / ALL 연산자는 배열 인덱스에서 작동하지 않습니다. 색인을 염두에두고있는 경우 :

SELECT COUNT(*) FROM "messages" WHERE 3 && recipient_ids

그리고 부정적인 :

SELECT COUNT(*) FROM "messages" WHERE NOT (3 && recipient_ids)

그런 다음 다음과 같이 색인을 만들 수 있습니다.

CREATE INDEX recipient_ids_idx on tableName USING GIN(recipient_ids)

다른 답변과 달리이 답변은 실제로 PostgreSQL 배열 중첩 연산자를 사용합니다. &&
Ceiling Gecko

6
이것은 서면으로 작동하지 않습니다. && 및 @>와 같은 배열 연산자는 두 요소가 모두 배열이어야하며 3은 그렇지 않습니다. 이것이 작동하려면 쿼리를 다음과 같이 작성해야합니다 SELECT COUNT(*) FROM "messages" WHERE ARRAY[3] && recipient_ids..
Dologan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.