쿼리로 그룹 내의 필드 문자열을 연결하는 방법을 찾고 있습니다. 예를 들어 테이블이 있습니다.
ID COMPANY_ID EMPLOYEE
1 1 Anna
2 1 Bill
3 2 Carol
4 2 Dave
그리고 company_id별로 그룹화하여 다음과 같은 것을 얻었습니다.
COMPANY_ID EMPLOYEE
1 Anna, Bill
2 Carol, Dave
mySQL에는이 group_concat 을 수행하는 내장 함수가 있습니다.
답변
PostgreSQL 9.0 이상 :
최신 버전의 Postgres (2010 년 말부터)에는 string_agg(expression, delimiter)
구분 기호 문자열을 지정할 수 있도록하면서 질문에 대한 내용을 정확하게 수행 하는 기능이 있습니다.
SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;
Postgres 9.0은 또한 모든 집계 표현식에서ORDER BY
절 을 지정하는 기능을 추가했습니다 . 그렇지 않으면 순서가 정의되지 않습니다. 따라서 다음과 같이 작성할 수 있습니다.
SELECT company_id, string_agg(employee, ', ' ORDER BY employee)
FROM mytable
GROUP BY company_id;
또는 실제로 :
SELECT string_agg(actor_name, ', ' ORDER BY first_appearance)
PostgreSQL 8.4 이상 :
PostgreSQL 8.4 (2009) 는 값을 배열로 연결하는 집계 함수array_agg(expression)
를 도입 했습니다 . 그런 다음 array_to_string()
원하는 결과를 제공하는 데 사용할 수 있습니다.
SELECT company_id, array_to_string(array_agg(employee), ', ')
FROM mytable
GROUP BY company_id;
string_agg
8.4 이전 버전의 경우 :
9.0 이전의 데이터베이스에 대한 호환성 심을 찾는 사람이 있다면 string_agg
,ORDER BY
조항 .
따라서 아래 정의에서는 9.x Postgres DB와 동일하게 작동합니다.
SELECT string_agg(name, '; ') AS semi_colon_separated_names FROM things;
그러나 이것은 구문 오류입니다.
SELECT string_agg(name, '; ' ORDER BY name) AS semi_colon_separated_names FROM things;
--> ERROR: syntax error at or near "ORDER"
PostgreSQL 8.3에서 테스트되었습니다.
CREATE FUNCTION string_agg_transfn(text, text, text)
RETURNS text AS
$$
BEGIN
IF $1 IS NULL THEN
RETURN $2;
ELSE
RETURN $1 || $3 || $2;
END IF;
END;
$$
LANGUAGE plpgsql IMMUTABLE
COST 1;
CREATE AGGREGATE string_agg(text, text) (
SFUNC=string_agg_transfn,
STYPE=text
);
맞춤형 변형 (모든 Postgres 버전)
9.0 이전에는 문자열을 연결하는 내장 집계 함수가 없었습니다. Vajda Gabo가이 메일 링리스트 post에서 제안한 가장 간단한 사용자 정의 구현 은 내장 textcat
함수 ( ||
연산자 뒤에 있음 )를 사용하는 것입니다.
CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);
이렇게하면 구분자가없는 모든 문자열을 간단하게 붙입니다. 끝에 “,”를 삽입하지 않고 그 사이에 “,”를 삽입하려면 자체 연결 기능을 만들고 위의 “textcat”을 대체 할 수 있습니다. 다음은 8.3.12에서 함께 테스트 한 것입니다.
CREATE FUNCTION commacat(acc text, instr text) RETURNS text AS $$
BEGIN
IF acc IS NULL OR acc = '' THEN
RETURN instr;
ELSE
RETURN acc || ', ' || instr;
END IF;
END;
$$ LANGUAGE plpgsql;
이 버전은 행의 값이 null이거나 비어 있어도 쉼표를 출력하므로 다음과 같이 출력됩니다.
a, b, c, , e, , g
추가 출력을 위해 쉼표를 제거하려면 다음을 수행하십시오.
a, b, c, e, g
그런 다음 ELSIF
함수에 다음과 같이 검사를 추가 하십시오.
CREATE FUNCTION commacat_ignore_nulls(acc text, instr text) RETURNS text AS $$
BEGIN
IF acc IS NULL OR acc = '' THEN
RETURN instr;
ELSIF instr IS NULL OR instr = '' THEN
RETURN acc;
ELSE
RETURN acc || ', ' || instr;
END IF;
END;
$$ LANGUAGE plpgsql;
답변
Postgres 내장 배열 함수를 사용하는 것은 어떻습니까? 최소한 8.4에서 이것은 즉시 작동합니다.
SELECT company_id, array_to_string(array_agg(employee), ',')
FROM mytable
GROUP BY company_id;
답변
PostgreSQL 9.0부터 string_agg 라는 집계 함수를 사용할 수 있습니다 . 새 SQL은 다음과 같아야합니다.
SELECT company_id, string_agg(employee, ', ')
FROM mytable
GROUP BY company_id;
답변
검색 후 답을 찾았 기 때문에 답변에 대한 크레딧이 없다고 주장합니다.
내가 모르는 것은 PostgreSQL이 CREATE AGGREGATE 를 사용하여 자신의 집계 함수를 정의 할 수 있다는 것입니다
PostgreSQL 목록 의이 게시물 은 필요한 작업을 수행하는 함수를 만드는 것이 얼마나 간단한지를 보여줍니다.
CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);
SELECT company_id, textcat_all(employee || ', ')
FROM mytable
GROUP BY company_id;
답변
이미 언급했듯이, 자신 만의 집계 함수를 만드는 것이 옳은 일입니다. 내 연결 집계 함수는 다음과 같습니다 ( 프랑스어로 세부 정보를 찾을 수 있음 ).
CREATE OR REPLACE FUNCTION concat2(text, text) RETURNS text AS '
SELECT CASE WHEN $1 IS NULL OR $1 = \'\' THEN $2
WHEN $2 IS NULL OR $2 = \'\' THEN $1
ELSE $1 || \' / \' || $2
END;
'
LANGUAGE SQL;
CREATE AGGREGATE concatenate (
sfunc = concat2,
basetype = text,
stype = text,
initcond = ''
);
그런 다음 다음과 같이 사용하십시오.
SELECT company_id, concatenate(employee) AS employees FROM ...
답변
8.4로 업그레이드 할 경우이 최신 공지 목록 스 니펫이 유용 할 수 있습니다.
8.4에서 매우 효과적인 네이티브 함수가 나올 때까지 PostgreSQL 설명서에서 array_accum () 함수를 추가하여 열을 배열로 롤업 할 수 있습니다. 그런 다음 응용 프로그램 코드에서 사용하거나 array_to_string ()과 함께 형식을 지정할 수 있습니다 목록으로 :
8.4 개발 문서에 링크했지만 아직이 기능을 나열하지 않은 것 같습니다.
답변
Postgres 문서를 사용하여 Kev의 답변에 후속 :
먼저 요소의 배열을 만든 다음 내장 array_to_string
함수 를 사용하십시오 .
CREATE AGGREGATE array_accum (anyelement)
(
sfunc = array_append,
stype = anyarray,
initcond = '{}'
);
select array_to_string(array_accum(name),'|') from table group by id;