2017-02-11 9 views
2

다음 사용자 지정 저장 기능 -PostgreSQL 9.6 및 더 낮은 버전에서 배열을 임의로 이동하는 방법은 무엇입니까?

CREATE OR REPLACE FUNCTION words_shuffle(in_array varchar[]) 
     RETURNS varchar[] AS 
$func$ 
     SELECT array_agg(letters.x) FROM 
     (SELECT UNNEST(in_array) x ORDER BY RANDOM()) letters; 
$func$ LANGUAGE sql STABLE; 

는 PostgreSQL의 9.5.3에 문자 배열을 셔플되었다

words=> select words_shuffle(ARRAY['a','b','c','d','e','f']); 
words_shuffle 
--------------- 
{c,d,b,a,e,f} 
(1 row) 

하지만 지금은 PostgreSQL을 전환 한 후에는 기능 작동이 중지 9.6.2 :

:
words=> select words_shuffle(ARRAY['a','b','c','d','e','f']); 
words_shuffle 
--------------- 
{a,b,c,d,e,f} 
(1 row) 

아마 RANDOM BY 순서는() 작동이 중지 때문에

words=> select unnest(ARRAY['a','b','c','d','e','f']) order by random(); 
unnest 
-------- 
a 
b 
c 
d 
e 
f 
(6 rows) 

새로운 PostgreSQL 9.6 및 9.5에서도 작동하는 문자 배열을 더 잘 만드는 방법을 찾고 있습니다.

Pl/PgSQL 기능을 사용하는 my word game 개발에 필요합니다.

UPDATE :

대답 Tom Lane에 의해 다음 TARGETLIST에 SRFs의

확장은 이제 BY ORDER 후 발생합니다. 그래서 ORDER BY는 하나의 더미 행을 정렬하고 그 다음에 unnest 이 발생합니다.

https://git.postgresql.org/gitweb/?p=postgresql.git&a=commitdiff&h=9118d03a8

답변

5

일반적 복귀 기능 세트 FROM 절에 배치되어야한다 the documentation 들어

select array_agg(u order by random()) 
from unnest(array['a','b','c','d','e','f']) u 

    array_agg 
--------------- 
{d,f,b,e,c,a} 
(1 row) 

(강조)를 첨가 :

을 현재 기능 세트를 리턴 할 수도 쿼리의 선택 목록에서 호출 할 수 있습니다. 쿼리가 자체적으로 생성하는 각 행에 대해 set을 반환하는 함수가 호출되고 함수 행의 각 요소에 대해 출력 행이 생성됩니다. 그러나이 기능은 더 이상 사용되지 않으며이며 향후 릴리스에서 제거 될 수 있습니다.

+0

'from' 절과'select'의 차이점은 실제로 이것이 작동을 멈춘 이유와 아무런 관련이 없습니다. 대답은 정확하고 정서는 정확하지만 (행 생성 함수를'from' 절에 넣음) 추론은 꺼져 있습니다. –

+0

필자는'SELECT' 절에서 SRF를 결코 사용하지 않기 때문에 그 문제에 대해 전혀 생각 해보지 않았습니다. 질문에 설명 된 사례가 SRF의 오용으로 인한 알려진 단일 문제가 아니기 때문에 규칙을 채택해야한다고 생각합니다. – klin

1

의심의 여지를 참조하십시오, 이것은 변화 인해 최적화의 일부 "개선"로 설정합니다. 문서 종류에 따르면 이것이 작동한다는 것을 감안할 때 실망 스럽습니다.

그러나, 나는 당신이 하위 쿼리에 의존하지 제안했다 :이 또한 포스트 그레스의 주문 버전에서 작동합니다

SELECT array_agg(letters.x ORDER BY random()) 
FROM UNNEST(in_array) l(x); 

.

documentation는 말한다 :

또는 정렬 된 서브 쿼리에서 입력 값을 제공하는 일반적으로 작동합니다. 예를 들어 :

SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab; 

는 그러나이 구문은 SQL 표준에서 허용되지 않습니다, 및 다른 데이터베이스 시스템에 이식 할 수 없습니다 입니다.

는 (I 자유롭게 "일반적으로 작동합니다"보장하는 것은 아닙니다. 그러나 문서에 이하의 코드 샘플 정말 오해의 소지가 갖는 것은. 왜 집계에 ORDER BY 절을 사용하여 올바른 샘플을 표시하지 않습니다 인정 기능?)

https://www.postgresql.org/docs/9.5/static/functions-aggregate.html