Postgresql_DB_가이드

테이블 표현식

구일칠구 2022. 8. 6. 14:07

테이블 표현식 은 테이블을 계산합니다. 테이블 표현식에는 FROM선택적으로 WHERE, GROUP BY및 HAVING절이 오는 절이 포함됩니다. 간단한 테이블 표현식은 디스크의 테이블, 즉 기본 테이블을 참조하지만 더 복잡한 표현식을 사용하여 기본 테이블을 다양한 방식으로 수정하거나 결합할 수 있습니다.

테이블 표현식 의 선택적 WHERE, GROUP BY및 HAVING절은 절에서 파생된 테이블에서 수행되는 연속 변환의 파이프라인을 지정합니다 FROM. 이러한 모든 변환은 쿼리의 출력 행을 계산하기 위해 선택 목록에 전달되는 행을 제공하는 가상 테이블을 생성합니다.

7.2.1. FROM조항 _

FROM절은 쉼표로 구분된 테이블 참조 목록에 제공된 하나 이상의 다른 테이블에서 테이블을 파생합니다.

에서 table_reference[ , table_reference[ , ... ] ]
  

테이블 참조는 테이블 이름(스키마 한정 가능) 또는 파생 테이블(예: 하위 쿼리, JOIN구성 또는 이들의 복잡한 조합)일 수 있습니다. 절 에 둘 이상의 테이블 참조가 나열 FROM되면 테이블이 교차 조인됩니다(즉, 해당 행의 데카르트 곱이 형성됩니다. 아래 참조). 목록 의 결과는 , 및 절 FROM에 의해 변환될 수 있는 중간 가상 테이블 이며 최종적으로 전체 테이블 표현식의 결과입니다.WHEREGROUP BYHAVING

테이블 참조가 테이블 상속 계층 구조의 상위 테이블에 이름을 지정할 때 테이블 참조는 키워드 ONLY가 테이블 이름 앞에 있지 않는 한 해당 테이블뿐만 아니라 모든 하위 테이블의 행을 생성합니다. 그러나 참조는 명명된 테이블에 나타나는 열만 생성합니다. 하위 테이블에 추가된 열은 무시됩니다.

ONLY테이블 이름 앞에 쓰는 대신 테이블 이름 *뒤에 써서 하위 테이블이 포함되도록 명시적으로 지정할 수 있습니다. 이제 하위 테이블 검색이 항상 기본 동작이기 때문에 이 구문을 더 이상 사용할 실제 이유가 없습니다. 그러나 이전 릴리스와의 호환성을 위해 지원됩니다.

7.2.1.1. 조인된 테이블

조인된 테이블은 특정 조인 유형의 규칙에 따라 두 개의 다른(실제 또는 파생된) 테이블에서 파생된 테이블입니다. 내부, 외부 및 교차 조인을 사용할 수 있습니다. 조인된 테이블의 일반 구문은 다음과 같습니다.

T1 join_type T2[ ]
    join_condition 

모든 유형의 조인은 함께 연결되거나 중첩될 수 있습니다. 둘 중 하나 또는 둘 다 T1조인 된 T2테이블이 될 수 있습니다. JOIN조인 순서를 제어하기 위해 절 주위에 괄호를 사용할 수 있습니다 . 괄호가 없으면 JOIN절이 왼쪽에서 오른쪽으로 중첩됩니다.

조인 유형

교차 조인
T1크로스 조인T2
      

T1와 의 가능한 모든 행 조합 T2(즉, 데카르트 곱)에 대해 조인된 테이블에는 의 모든 열과 의 모든 열로 구성된 행이 포함 T1됩니다 T2. 테이블에 각각 N 및 M 행이 있는 경우 조인된 테이블에는 N * M 행이 있습니다.

FROM T1 CROSS JOIN T2와 동일합니다 (아래 참조). 와도 동일합니다 .FROM T1 INNER JOIN T2 ON TRUEFROM T1, T2

메모

JOIN이 후자의 동등성은 쉼표보다 더 밀접하게 바인딩 되기 때문에 두 개 이상의 테이블이 나타날 때 정확히 유지되지 않습니다 . 예를 들어 첫 번째 경우에는 can이 참조할 수 있지만 두 번째 경우에는 참조할 수 없기 때문에 같지 않습니다.FROM T1 CROSS JOIN T2 INNER JOIN T3 ON conditionFROM T1, T2 INNER JOIN T3 ON conditionconditionT1

적격 조인
T1{ [ 내부 ] | { 왼쪽 | 오른쪽 | 전체 } [ 외부 ] } 조인 T2ON { [ 내부 ] | { 왼쪽 | 오른쪽 | 전체 } [ 외부 ] } ( )
      NATURAL { [ 내부 ] | { 왼쪽 | 오른쪽 | 전체 } [ 외부 ] } 조인boolean_expression
      T1T2join column listT1T2
      

and 는 모든 형태에서 선택 사항입니다 INNER. 기본값입니다. , 외부 조인을 의미합니다.OUTERINNERLEFTRIGHTFULL

조인 조건 ON또는 USING절에 지정 되거나 단어로 암시적으로 지정됩니다 NATURAL. 조인 조건은 아래에 자세히 설명된 대로 두 소스 테이블에서 " 일치 " 로 간주되는 행을 결정 합니다.

규정된 조인의 가능한 유형은 다음과 같습니다.

INNER JOIN

T1의 각 행 R1에 대해 조인된 테이블에는 R1과의 조인 조건을 충족하는 T2의 각 행에 대한 행이 있습니다.

LEFT OUTER JOIN

먼저 내부 조인이 수행됩니다. 그런 다음 T2의 어떤 행과도 조인 조건을 충족하지 않는 T1의 각 행에 대해 조인된 행이 T2의 열에 null 값으로 추가됩니다. 따라서 조인된 테이블에는 항상 T1의 각 행에 대해 하나 이상의 행이 있습니다.

RIGHT OUTER JOIN

먼저 내부 조인이 수행됩니다. 그런 다음 T1의 어떤 행과도 조인 조건을 충족하지 않는 T2의 각 행에 대해 조인된 행이 T1의 열에 null 값으로 추가됩니다. 이것은 왼쪽 조인의 반대입니다. 결과 테이블에는 항상 T2의 각 행에 대한 행이 있습니다.

FULL OUTER JOIN

먼저 내부 조인이 수행됩니다. 그런 다음 T2의 어떤 행과도 조인 조건을 충족하지 않는 T1의 각 행에 대해 조인된 행이 T2의 열에 null 값으로 추가됩니다. 또한 T1의 어떤 행과도 조인 조건을 만족하지 않는 T2의 각 행에 대해 T1의 열에 null 값이 있는 조인된 행이 추가됩니다.

절은 가장 일반적인 종류의 조인 조건 입니다. 절 ON에서 사용되는 것과 같은 종류의 부울 값 표현식을 사용합니다 . 표현식이 true로 평가되는 경우 일치하는 WHERE행 쌍입니다 .T1T2ON

USING절은 조인의 양쪽이 조인 열에 대해 동일한 이름을 사용하는 특정 상황을 활용할 수 있는 약식입니다. 쉼표로 구분된 공유 열 이름 목록을 사용하고 각각에 대한 동등 비교를 포함하는 조인 조건을 형성합니다. 예를 들어, 결합 T1및 T2with USING (a, b)는 결합 조건을 생성합니다 .ON T1.a = T2.a AND T1.b = T2.b

또한 의 출력은 JOIN USING중복 열을 억제합니다. 일치하는 열은 값이 같아야 하므로 두 열을 모두 인쇄할 필요가 없습니다. 의 모든 열을 생성한 다음 의 모든 열 JOIN ON생성 하는 동안 나열된 각 열 쌍(나열된 순서대로)에 대해 하나의 출력 열을 생성하고 의 나머지 열과 의 나머지 열을 생성 합니다.T1T2JOIN USINGT1T2

마지막으로 NATURAL는 의 약식 형식입니다 . 두 입력 테이블에 나타나는 모든 열 이름으로 구성된 목록 USING을 형성합니다 . USING와 마찬가지로 USING이러한 열은 출력 테이블에 한 번만 나타납니다. 공통 열 이름이 없으면 NATURAL JOIN처럼 동작 JOIN ... ON TRUE하여 교차 곱 조인을 생성합니다.

메모

USING나열된 열만 결합되기 때문에 조인된 관계의 열 변경으로부터 상당히 안전합니다. NATURAL새로운 일치 열 이름이 나타나도록 하는 두 관계에 대한 스키마 변경으로 인해 조인이 해당 새 열도 결합하게 되므로 훨씬 더 위험합니다.

이를 종합하기 위해 다음과 같은 테이블이 있다고 가정합니다 t1.

번호 | 이름
    ---+------
    1 | ㅏ
    2 | 비
    3 | 씨
    

t2:

번호 | 값
    ---+-------
    1 | 트리플 엑스
    3 | 요이
    5 | 쿨쿨
    

다양한 조인에 대해 다음과 같은 결과를 얻습니다.

=> SELECT * FROM t1 CROSS JOIN t2;
    번호 | 이름 | 번호 | 값
    -----+------+-----+-------
    1 | | 1 | 트리플 엑스
    1 | | 3 | 요이
    1 | | 5 | 쿨쿨
    2 | ㄴ | 1 | 트리플 엑스
    2 | ㄴ | 3 | 요이
    2 | ㄴ | 5 | 쿨쿨
    3 | ㄷ | 1 | 트리플 엑스
    3 | ㄷ | 3 | 요이
    3 | ㄷ | 5 | 쿨쿨
    (9줄)
    
    => SELECT * FROM t1 INNER JOIN t2 ON t1.num = t2.num;
    번호 | 이름 | 번호 | 값
    -----+------+-----+-------
    1 | | 1 | 트리플 엑스
    3 | ㄷ | 3 | 요이
    (2줄)
    
    => SELECT * FROM t1 INNER JOIN t2 USING (num);
    번호 | 이름 | 값
    -----+------+-------
    1 | | 트리플 엑스
    3 | ㄷ | 요이
    (2줄)
    
    => SELECT * FROM t1 NATURAL INNER JOIN t2;
    번호 | 이름 | 값
    -----+------+-------
    1 | | 트리플 엑스
    3 | ㄷ | 요이
    (2줄)
    
    => SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num;
    번호 | 이름 | 번호 | 값
    -----+------+-----+-------
    1 | | 1 | 트리플 엑스
    2 | ㄴ | |
    3 | ㄷ | 3 | 요이
    (3줄)
    
    => SELECT * FROM t1 LEFT JOIN t2 USING (num);
    번호 | 이름 | 값
    -----+------+-------
    1 | | 트리플 엑스
    2 | ㄴ |
    3 | ㄷ | 요이
    (3줄)
    
    => SELECT * FROM t1 RIGHT JOIN t2 ON t1.num = t2.num;
    번호 | 이름 | 번호 | 값
    -----+------+-----+-------
    1 | | 1 | 트리플 엑스
    3 | ㄷ | 3 | 요이
    | | 5 | 쿨쿨
    (3줄)
    
    => SELECT * FROM t1 FULL JOIN t2 ON t1.num = t2.num;
    번호 | 이름 | 번호 | 값
    -----+------+-----+-------
    1 | | 1 | 트리플 엑스
    2 | ㄴ | |
    3 | ㄷ | 3 | 요이
    | | 5 | 쿨쿨
    (4줄)
    

로 지정된 조인 조건 ON에는 조인과 직접 관련이 없는 조건도 포함될 수 있습니다. 이것은 일부 쿼리에 유용할 수 있지만 신중하게 생각해야 합니다. 예를 들어:

=> SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num AND t2.value = 'xxx';
    번호 | 이름 | 번호 | 값
    -----+------+-----+-------
    1 | | 1 | 트리플 엑스
    2 | ㄴ | |
    3 | ㄷ | |
    (3줄)
    

절 에 제한을 두는 것은 WHERE다른 결과를 생성합니다:

=> SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num WHERE t2.value = 'xxx';
    번호 | 이름 | 번호 | 값
    -----+------+-----+-------
    1 | | 1 | 트리플 엑스
    (1줄)
    

이는 절에 있는 제한 사항 은 조인 전에ON 처리되고 절 에 있는 제한 사항은 조인 후에 처리되기 때문 입니다. 이는 내부 조인에서는 중요하지 않지만 외부 조인에서는 매우 중요합니다.WHERE

7.2.1.2. 테이블 및 열 별칭

나머지 쿼리에서 파생 테이블에 대한 참조에 사용할 테이블 및 복합 테이블 참조에 임시 이름을 지정할 수 있습니다. 이것을 테이블 별칭 이라고 합니다 .

테이블 별명을 작성하려면 다음을 작성하십시오.

AS table_reference에서alias
    

또는

에서table_reference alias
    

AS키워드는 선택적 노이즈입니다 . alias모든 식별자가 될 수 있습니다.

테이블 별칭의 일반적인 적용은 조인 절을 읽을 수 있도록 유지하기 위해 긴 테이블 이름에 짧은 식별자를 할당하는 것입니다. 예를 들어:

SELECT * FROM some_very_long_table_name s JOIN another_fairly_long_name a ON s.id = a.num;
    

별칭은 현재 쿼리에 관한 한 테이블 참조의 새 이름이 됩니다. 쿼리의 다른 곳에서 원래 이름으로 테이블을 참조할 수 없습니다. 따라서 이것은 유효하지 않습니다.

SELECT * FROM my_table AS m WHERE my_table.a > 5; -- 잘못된
    

테이블 별칭은 주로 표기상의 편의를 위한 것이지만 테이블을 자체에 결합할 때 사용해야 합니다. 예:

SELECT * FROM people AS mother JOIN people AS child ON mother.id = child.mother_id;
    

또한 테이블 참조가 하위 쿼리인 경우 별칭이 필요합니다( 섹션 7.2.1.3 참조 ).

괄호는 모호성을 해결하는 데 사용됩니다. 다음 예에서 첫 번째 문 b은 의 두 번째 인스턴스에 my_table별칭을 할당하지만 두 번째 문은 조인 결과에 별칭을 할당합니다.

SELECT * FROM my_table AS a CROSS JOIN my_table AS b ...
    SELECT * FROM (my_table AS a CROSS JOIN my_table) AS b ...
    

테이블 별칭의 또 다른 형식은 테이블 자체뿐만 아니라 테이블의 열에 임시 이름을 지정합니다.

에서 table_reference[ 그대로 ] alias( column1[ , column2[ , ... ] ] )
    

실제 테이블에 열이 있는 것보다 적은 열 별칭이 지정되면 나머지 열의 이름은 변경되지 않습니다. 이 구문은 자체 조인 또는 하위 쿼리에 특히 유용합니다.

JOIN별칭이 절의 출력에 적용되면 별칭은 JOIN. 예를 들어:

SELECT a.* FROM my_table AS a JOIN your_table AS b ON ...
    

유효한 SQL이지만:

SELECT a.* FROM (my_table AS a JOIN your_table AS b ON ...) AS c
    

유효하지 않습니다. 테이블 별칭 a은 별칭 외부에서 볼 수 없습니다 c.

7.2.1.3. 하위 쿼리

파생 테이블을 지정하는 하위 쿼리는 괄호로 묶어야 하며 테이블 별칭 이름을 할당해야 합니다( 섹션 7.2.1.2 참조). 예를 들어:

FROM (SELECT * FROM table1) AS alias_name
    

이 예는 에 해당합니다 FROM table1 AS alias_name. 일반 조인으로 축소할 수 없는 더 흥미로운 경우는 하위 쿼리가 그룹화 또는 집계를 포함할 때 발생합니다.

VALUES하위 쿼리는 목록 일 수도 있습니다 .

FROM (VALUES('앤', '스미스'), ('밥', '존스'), ('조', '블로'))
    AS 이름(이름, 성)
    

다시 말하지만 테이블 별칭이 필요합니다. 목록 의 열에 별칭 이름을 할당하는 VALUES것은 선택 사항이지만 좋은 방법입니다. 자세한 내용은 섹션 7.7 을 참조하십시오 .

7.2.1.4. 테이블 기능

테이블 함수는 기본 데이터 유형(스칼라 유형) 또는 복합 데이터 유형(테이블 행)으로 구성된 일련의 행을 생성하는 함수입니다. FROM쿼리 절 에서 테이블, 뷰 또는 하위 쿼리처럼 사용됩니다 . 테이블 함수에서 반환된 열은 테이블, 뷰 또는 하위 쿼리의 열과 동일한 방식으로 SELECT, JOIN, 또는 절에 포함될 수 있습니다 .WHERE

테이블 함수는 구문을 사용하여 결합할 수도 있으며 ROWS FROM결과는 병렬 열에 반환됩니다. 이 경우 결과 행의 수는 가장 큰 함수 결과의 행 수이며 더 작은 결과는 일치하는 null 값으로 채워집니다.

function_call[ 순서가 있음 ] [ [ 그대로 ] table_alias[ ( column_alias[ , ... ]) ] ]
    ROWS FROM( function_call[ , ... ] ) [ 순서가 있는 경우 ] [ [ AS ] table_alias[ ( column_alias[ , ... ]) ] ]
    

WITH ORDINALITY절이 지정되면 함수 결과 열에 유형의 추가 열이 추가 bigint됩니다. 이 열은 1부터 시작하여 함수 결과 집합의 행 번호를 지정합니다. (이는 에 대한 SQL 표준 구문의 일반화입니다 UNNEST ... WITH ORDINALITY.) 기본적으로 순서 열이 호출 ordinality되지만 다음을 사용하여 다른 열 이름을 할당할 수 있습니다. AS절.

특수 테이블 함수 UNNEST는 임의의 수의 배열 매개변수와 함께 호출될 수 있으며, 마치 UNNEST( 9.19절 ) 각 매개변수에 대해 개별적으로 호출되고 ROWS FROM구성을 사용하여 결합된 것처럼 해당 수의 열을 반환합니다.

UNNEST( array_expression[ , ... ] ) [ 순서가 있음 ] [ [ AS ] table_alias[ ( column_alias[ , ... ]) ] ]
    

no table_alias를 지정하면 함수 이름이 테이블 이름으로 사용됩니다. 구성 의 경우 ROWS FROM()첫 번째 함수의 이름이 사용됩니다.

열 별칭이 제공되지 않으면 기본 데이터 유형을 반환하는 함수의 경우 열 이름도 함수 이름과 동일합니다. 복합 유형을 반환하는 함수의 경우 결과 열은 유형의 개별 속성 이름을 가져옵니다.

몇 가지 예:

CREATE TABLE foo (fooid int, foosubid int, fooname 텍스트);
    
    CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS $$
    SELECT * FROM FOO WHERE fooid = $1;
    $$ 언어 SQL;
    
    SELECT * FROM getfoo(1) AS t1;
    
    선택 * 푸에서
    WHERE foosubid IN (
    선택 foosubid
    FROM getfoo(foo.fooid) z
    WHERE z.fooid = foo.fooid
    );
    
    뷰 만들기 vw_getfoo AS SELECT * FROM getfoo(1);
    
    SELECT * FROM vw_getfoo;
    

어떤 경우에는 호출 방법에 따라 다른 열 집합을 반환할 수 있는 테이블 함수를 정의하는 것이 유용합니다. 이를 지원하기 위해 테이블 ​​함수는 매개변수 record없이 의사 유형을 반환하는 것으로 선언될 수 있습니다 OUT. 이러한 함수를 쿼리에 사용할 때 예상되는 행 구조를 쿼리 자체에 지정해야 시스템이 쿼리를 구문 분석하고 계획하는 방법을 알 수 있습니다. 이 구문은 다음과 같습니다.

function_call[ 그대로 ] alias( column_definition[ , ... ])
    function_call그대로 [ alias] ( column_definition[ , ... ])
    행 FROM( ... function_callAS ( column_definition[ , ... ]) [ , ... ] )
    

ROWS FROM()구문을 사용하지 않는 경우 목록은 항목 column_definition에 첨부할 수 있는 열 별칭 목록을 대체합니다 . FROM열 정의의 이름은 열 별칭으로 사용됩니다. ROWS FROM()구문을 사용할 때 column_definition목록을 각 멤버 함수에 개별적으로 첨부할 수 있습니다. 또는 멤버 함수가 하나만 있고 WITH ORDINALITY절이 없는 경우 column_definition뒤에 오는 열 별칭 목록 대신 목록을 작성할 수 있습니다 ROWS FROM().

다음 예를 고려하십시오.두 기능을 단일 FROM대상으로 결합합니다. 첫 번째 열과 두 번째 json_to_recordset()열 두 개를 반환하도록 지시받았습니다 . 의 결과 가 직접 사용됩니다. 절은 열 값을 정수로 정렬합니다.integertextgenerate_series()ORDER BY

7.2.1.5. LATERAL하위 쿼리

에 나타나는 하위 쿼리 FROM는 키워드 앞에 올 수 있습니다 LATERAL. 이를 통해 이전 FROM항목에서 제공한 열을 참조할 수 있습니다. (없이 LATERAL각 하위 쿼리는 독립적으로 평가되므로 다른 FROM항목을 상호 참조할 수 없습니다.)

에 나타나는 테이블 기능 FROM앞에 키워드가 올 수도 LATERAL있지만 기능의 경우 키워드는 선택 사항입니다. FROM함수의 인수는 어떤 경우에도 선행 항목에서 제공한 열에 대한 참조를 포함할 수 있습니다 .

항목은 목록의 최상위 수준이나 트리 내에 나타날 LATERAL수 있습니다 . 후자의 경우 오른쪽에 있는 항목의 왼쪽에 있는 항목을 참조할 수도 있습니다 .FROMJOINJOIN

FROM항목에 상호 참조가 포함 LATERAL경우 평가는 다음과 같이 진행됩니다. FROM상호 참조된 열을 제공하는 항목의 각 행 또는 열을 제공하는 여러 FROM항목 의 행 집합에 대해 LATERAL항목은 해당 행 또는 행 집합의 열의 값. 결과 행은 평소와 같이 계산된 행과 결합됩니다. 이것은 열 소스 테이블의 각 행 또는 행 집합에 대해 반복됩니다.

의 사소한 예 LATERAL는

SELECT * FROM FOO, LATERAL (SELECT * FROM 바 WHERE bar.id = foo.bar_id) ss;
    

이것은 더 일반적인 것과 정확히 동일한 결과를 가지므로 특별히 유용하지 않습니다.

SELECT * foo, bar WHERE bar.id = foo.bar_id;
    

LATERAL조인할 행을 계산하는 데 교차 참조된 열이 필요할 때 주로 유용합니다. 일반적인 응용 프로그램은 집합 반환 함수에 대한 인수 값을 제공합니다. 예를 들어, vertices(polygon)다각형의 정점 집합을 반환한다고 가정하면 다음을 사용하여 테이블에 저장된 다각형의 밀접하게 연결된 정점을 식별할 수 있습니다.

p1.id, p2.id, v1, v2 선택
    FROM 폴리곤 p1, 폴리곤 p2,
    측면 정점(p1.poly) v1,
    측면 정점(p2.poly) v2
    WHERE (v1 <-> v2) < 10 AND p1.id != p2.id;
    

이 쿼리도 작성할 수 있습니다.

p1.id, p2.id, v1, v2 선택
    FROM 폴리곤 p1 CROSS JOIN LATERAL 정점(p1.poly) v1,
    다각형 p2 CROSS JOIN LATERAL 정점(p2.poly) v2
    WHERE (v1 <-> v2) < 10 AND p1.id != p2.id;
    

또는 여러 다른 동등한 공식으로. (이미 언급했듯이 LATERAL이 예제에서는 키워드가 필요하지 않지만 명확성을 위해 사용합니다.)

하위 쿼리가 행을 생성하지 않더라도 소스 행이 결과에 나타나도록 LEFT JOIN하는 하위 쿼리에 특히 편리 합니다. 예를 들어, 제조업체가 만든 제품의 이름을 반환하지만 우리 테이블의 일부 제조업체는 현재 제품을 생산하지 않는 경우 다음과 같은 제품을 찾을 수 있습니다.LATERALLATERALget_product_names()

m.이름 선택
    FROM 제조사 m LEFT JOIN LATERAL get_product_names(m.id) pname ON true
    WHERE pname이 NULL입니다.
    

7.2.2. WHERE조항 _

WHERE절의 구문은 다음과 같습니다.

어디search_condition
  

여기서 는 type 의 값을 반환하는 search_condition값 표현식( 섹션 4.2boolean 참조)입니다 .

After the processing of the FROM clause is done, each row of the derived virtual table is checked against the search condition. If the result of the condition is true, the row is kept in the output table, otherwise (i.e., if the result is false or null) it is discarded. The search condition typically references at least one column of the table generated in the FROM clause; this is not required, but otherwise the WHERE clause will be fairly useless.

Note

The join condition of an inner join can be written either in the WHERE clause or in the JOIN clause. For example, these table expressions are equivalent:

FROM a, b WHERE a.id = b.id AND b.val > 5
    

and:

FROM a INNER JOIN b ON (a.id = b.id) WHERE b.val > 5
    

or perhaps even:

FROM a NATURAL JOIN b WHERE b.val > 5
    

Which one of these you use is mainly a matter of style. The JOIN syntax in the FROM clause is probably not as portable to other SQL database management systems, even though it is in the SQL standard. For outer joins there is no choice: they must be done in the FROM clause. The ON or USING clause of an outer join is not equivalent to a WHERE condition, because it results in the addition of rows (for unmatched input rows) as well as the removal of rows in the final result.

Here are some examples of WHERE clauses:

SELECT ... FROM fdt WHERE c1 > 5
  
  SELECT ... FROM fdt WHERE c1 IN (1, 2, 3)
  
  SELECT ... FROM fdt WHERE c1 IN (SELECT c1 FROM t2)
  
  SELECT ... FROM fdt WHERE c1 IN (SELECT c3 FROM t2 WHERE c2 = fdt.c1 + 10)
  
  SELECT ... FROM fdt WHERE c1 BETWEEN (SELECT c3 FROM t2 WHERE c2 = fdt.c1 + 10) AND 100
  
  SELECT ... FROM fdt WHERE EXISTS(SELECT c1 FROM t2 WHERE c2 > fdt.c1)
  

fdtFROM절 에서 파생된 테이블 입니다. WHERE절의 검색 조건을 충족하지 않는 행 은 에서 제거됩니다 fdt. 스칼라 하위 쿼리를 값 표현식으로 사용하는 것에 주목하십시오. 다른 쿼리와 마찬가지로 하위 쿼리는 복잡한 테이블 표현식을 사용할 수 있습니다. 또한 fdt하위 쿼리에서 참조되는 방식에 유의하십시오. 하위 쿼리의 파생된 입력 테이블에 있는 열의 이름이기도 한 경우 c1에만 fdt.c1한정이 필요합니다 . c1그러나 열 이름을 한정하면 필요하지 않은 경우에도 명확성이 추가됩니다. 이 예에서는 외부 쿼리의 열 명명 범위가 내부 쿼리로 확장되는 방법을 보여줍니다.

7.2.3. GROUP BY및 HAVING조항 _

필터 를 통과한 후 WHERE파생된 입력 테이블은 절을 사용하여 그룹화하고 GROUP BY절을 사용하여 그룹 행을 제거할 수 HAVING있습니다.

고르다select_list
  에서 ...
  [ 어디 ... ]
  그룹 기준 grouping_column_reference[ ,grouping_column_reference ]...
  

GROUP BY절은 나열된 모든 열에 동일한 값이 있는 테이블의 행을 함께 그룹화하는 데 사용됩니다. 열이 나열되는 순서는 중요하지 않습니다. 결과는 공통 ​​값을 갖는 각 행 세트를 그룹의 모든 행을 나타내는 하나의 그룹 행으로 결합하는 것입니다. 이는 출력의 중복성을 제거하고 이러한 그룹에 적용되는 집계를 계산하기 위해 수행됩니다. 예를 들어:

=> SELECT * FROM test1;
  엑스 | 와이
  ---+---
  | 삼
  ㄷ | 2
  ㄴ | 5
  | 1
  (4줄)
  
  => SELECT x FROM test1 GROUP BY x;
  엑스
  ---
  ㅏ
  비
  씨
  (3줄)
  

두 번째 쿼리에서는 각 그룹과 연관될 수 SELECT * FROM test1 GROUP BY x있는 열에 대한 단일 값이 없기 때문에 작성할 수 없습니다. y그룹화 기준 열은 각 그룹에 단일 값이 있으므로 선택 목록에서 참조할 수 있습니다.

일반적으로 테이블을 그룹화하면 에 나열되지 않은 열은 GROUP BY집계 표현식을 제외하고는 참조할 수 없습니다. 집계 표현식의 예는 다음과 같습니다.

=> SELECT x, sum(y) FROM test1 GROUP BY x;
  엑스 | 합집합
  ---+-----
  | 4
  ㄴ | 5
  ㄷ | 2
  (3줄)
  

다음 sum은 전체 그룹에 대해 단일 값을 계산하는 집계 함수입니다. 사용 가능한 집계 함수에 대한 자세한 내용은 9.21절 에서 찾을 수 있습니다 .

집계 표현식 없이 그룹화하면 열의 고유 값 집합을 효과적으로 계산합니다. DISTINCT이는 절 을 사용하여 달성할 수도 있습니다 ( 섹션 7.3.3 참조 ).

다음은 또 다른 예입니다. 모든 제품의 총 판매액이 아닌 각 제품의 총 판매액을 계산합니다.

SELECT product_id, p.name, (sum(s.units) * p.price) AS 판매
  FROM 제품 p LEFT JOIN 판매 s USING(product_id)
  GROUP BY product_id, p.name, p.price;
  

이 예에서 열 product_id, p.name, 및 열은 쿼리 선택 목록에서 참조되므로 절 p.price에 있어야 합니다 GROUP BY(아래 참조). 열 은 제품 판매를 나타내는 집계 표현식( )에서만 사용되므로 목록 s.units에 있을 필요는 없습니다 . 각 제품에 대해 쿼리는 제품의 모든 판매에 대한 요약 행을 반환합니다.GROUP BYsum(...)

제품 테이블이 기본 키가 되도록 설정되어 있으면 이름과 가격이 기능적으로 제품 ID에 종속 되므로 위의 예에서 product_id그룹화하는 것으로 충분 하므로 모호성이 없습니다. 각 제품 ID 그룹에 대해 반환할 이름 및 가격 값에 대한 정보입니다.product_id

엄격한 SQL에서는 GROUP BY원본 테이블의 열별로만 그룹화할 수 있지만 PostgreSQL 은 이를 확장 GROUP BY하여 선택 목록의 열별로 그룹화할 수도 있습니다. 단순 열 이름 대신 값 표현식으로 그룹화하는 것도 허용됩니다.

테이블이 를 사용하여 그룹화 GROUP BY되었지만 특정 그룹만 관심이 있는 경우, HAVING절과 마찬가지로 WHERE절을 사용하여 결과에서 그룹을 제거할 수 있습니다. 구문은 다음과 같습니다.

SELECT select_listFROM ... [ WHERE ... ] 그룹화 기준 ... HAVINGboolean_expression
  

절의 표현식은 HAVING그룹화된 표현식과 그룹화되지 않은 표현식(필연적으로 집계 함수를 포함함)을 모두 참조할 수 있습니다.

예시:

=> SELECT x, sum(y) FROM test1 GROUP BY x HAVING sum(y) > 3;
  엑스 | 합집합
  ---+-----
  | 4
  ㄴ | 5
  (2줄)
  
  => SELECT x, sum(y) FROM test1 GROUP BY x HAVING x < 'c';
  엑스 | 합집합
  ---+-----
  | 4
  ㄴ | 5
  (2줄)
  

다시, 더 현실적인 예:

SELECT product_id, p.name, (sum(s.units) * (p.price - p.cost)) AS profit
  FROM products p LEFT JOIN sales s USING (product_id)
  WHERE s.date > CURRENT_DATE - INTERVAL '4 weeks'
  GROUP BY product_id, p.name, p.price, p.cost
  HAVING sum(p.price * s.units) > 5000;
  

In the example above, the WHERE clause is selecting rows by a column that is not grouped (the expression is only true for sales during the last four weeks), while the HAVING clause restricts the output to groups with total gross sales over 5000. Note that the aggregate expressions do not necessarily need to be the same in all parts of the query.

If a query contains aggregate function calls, but no GROUP BY clause, grouping still occurs: the result is a single group row (or perhaps no rows at all, if the single row is then eliminated by HAVING). The same is true if it contains a HAVING clause, even without any aggregate function calls or GROUP BY clause.

7.2.4. GROUPING SETS, CUBE, and ROLLUP

More complex grouping operations than those described above are possible using the concept of grouping sets. The data selected by the FROM and WHERE clauses is grouped separately by each specified grouping set, aggregates computed for each group just as for simple GROUP BY clauses, and then the results returned. For example:

=> SELECT * FROM items_sold;
  brand | size | sales
  -------+------+-------
  Foo   | L    |  10
  Foo   | M    |  20
  바 | 남 | 15
  바 | 엘 | 5
  (4줄)
  
  => SELECT brand, size, sum(sales) FROM items_sold GROUP BY GROUPING SETS ((brand), (size), ());
  브랜드 | 크기 | 합집합
  -------+------+-----
  푸 | | 30
  바 | | 20
  | 엘 | 15
  | 남 | 35
  | | 50
  (5줄)
  

의 각 하위 목록은 0개 이상의 열 또는 표현식을 지정할 수 있으며 GROUPING SETS에 직접 있는 것처럼 동일한 방식으로 해석됩니다 . 빈 그룹화 집합은 위에서 절이 GROUP BY없는 집계 함수의 경우에 대해 설명한 것처럼 모든 행이 단일 그룹(입력 행이 없는 경우에도 출력됨)으로 집계됨을 의미합니다 .GROUP BY

그룹화 열 또는 표현식에 대한 참조는 해당 열이 표시되지 않는 그룹화 세트에 대한 결과 행의 널 값으로 대체됩니다. 특정 출력 행의 결과 그룹을 구별하려면 Table 9.61 을 참조하십시오 .

두 가지 일반적인 유형의 그룹화 집합을 지정하기 위해 속기 표기법이 제공됩니다. 형식의 절

롤업( e1, e2, e3, ... )
  

주어진 표현식 목록과 빈 목록을 포함한 목록의 모든 접두사를 나타냅니다. 따라서 그것은 동등하다

그룹화 세트(
  ( e1, e2, e3, ... ),
  ...
  ( e1, e2),
  ( e1),
  ( )
  )
  

이것은 일반적으로 계층적 데이터에 대한 분석에 사용됩니다. 예: 부서별, 부서별, 전사적 총 급여.

형식의 절

큐브( e1, e2, ... )
  

주어진 목록과 가능한 모든 하위 집합(즉, 거듭제곱 집합)을 나타냅니다. 따라서

큐브 ( a, b, c )
  

와 동등하다

그룹화 세트(
  ( a, b, c ),
  ( a, b ),
  ( a, c ),
  ( ㅏ ),
  ( b, c ),
  ( b ),
  ( 씨 ),
  ( )
  )
  

CUBE또는 절의 개별 요소는 ROLLUP개별 표현식이거나 괄호 안에 있는 요소의 하위 목록일 수 있습니다. 후자의 경우 하위 목록은 개별 그룹화 집합을 생성할 목적으로 단일 단위로 처리됩니다. 예를 들어:

큐브 ( (a, b), (c, d) )
  

와 동등하다

그룹화 세트(
  (a, b, c, d),
  ( a, b ),
  ( CD ),
  ( )
  )
  

그리고

롤업 ( a, (b, c), d )
  

와 동등하다

그룹화 세트(
  (a, b, c, d),
  ( a, b, c ),
  ( ㅏ ),
  ( )
  )
  

CUBE및 구문 은 절 ROLLUP에서 직접 사용하거나 GROUP BY절 내부에 중첩 하여 사용할 수 있습니다 GROUPING SETS. GROUPING SETS절이 다른 절 안에 중첩되어 있으면 내부 절의 모든 요소가 외부 절에 직접 작성된 것과 같은 효과가 있습니다.

여러 그룹화 항목이 단일 절에 지정된 경우 GROUP BY그룹화 세트의 최종 목록은 개별 항목의 외적입니다. 예를 들어:

GROUP BY a, CUBE(b, c), 그룹화 세트((d), (e))
  

와 동등하다

그룹화 세트별 그룹화(
  (a, b, c, d), (a, b, c, e),
  (a, b, d), (a, b, e),
  (a, c, d), (a, c, e),
  (a,d), (a,e)
  )
  

여러 그룹화 항목을 함께 지정할 때 그룹화 세트의 최종 세트에 중복 항목이 포함될 수 있습니다. 예를 들어:

그룹별 ROLLUP(a, b), ROLLUP(a, c)
  

와 동등하다

그룹화 세트별 그룹화(
  (a, b, c),
  (a, b),
  (a, b),
  (a, c),
  (ㅏ),
  (ㅏ),
  (a, c),
  (ㅏ),
  ()
  )
  

이러한 중복이 바람직하지 않은 경우 에서 DISTINCT직접 절을 사용하여 제거할 수 있습니다 GROUP BY. 그러므로:

GROUP BY DISTINCT ROLLUP(a, b), ROLLUP(a, c)
  

와 동등하다

그룹화 세트별 그룹화(
  (a, b, c),
  (a, b),
  (a, c),
  (ㅏ),
  ()
  )
  

SELECT DISTINCT출력 행에 여전히 중복 항목이 포함될 수 있으므로 이는 를 사용하는 것과 동일하지 않습니다 . 그룹화되지 않은 열에 NULL이 포함되어 있으면 동일한 열을 그룹화할 때 사용되는 NULL과 구별할 수 없습니다.

메모

구문 (a, b)은 일반적으로 표현식에서 행 생성자 로 인식됩니다 . 절 내 GROUP BY에서 이는 최상위 표현식에는 적용되지 않으며 (a, b)위에서 설명한 대로 표현식 목록으로 구문 분석됩니다. 어떤 이유로 그룹화 표현식에 행 생성자가 필요한ROW(a, b) 경우 .

7.2.5. 창 함수 처리

쿼리에 창 함수가 포함된 경우( 섹션 3.5 , 섹션 9.22 섹션 4.2.8 참조) 이러한 함수는 그룹화, 집계 및 HAVING필터링이 수행된 후에 평가됩니다. 즉, 쿼리가 집계, GROUP BY또는 HAVING를 사용하는 경우 창 함수에 표시되는 행은 FROM/ 의 원래 테이블 행 대신 그룹 행 WHERE입니다.

여러 창 함수가 사용되는 경우 해당 창 정의에 구문적으로 동일한 PARTITION BY및 ORDER BY절이 있는 모든 창 함수는 데이터에 대한 단일 패스에서 평가되도록 보장됩니다. ORDER BY따라서 순서를 고유하게 결정하지 않더라도 동일한 정렬 순서가 표시됩니다 . PARTITION BY단, 기능 이나 ORDER BY사양 이 다른 평가에 대해서는 보증하지 않습니다 . (이러한 경우 정렬 단계는 일반적으로 창 함수 평가의 전달 사이에 필요하며 정렬은 ORDER BY동등하다고 간주되는 행의 순서를 유지하도록 보장되지 않습니다.)

PARTITION BY현재 창 함수는 항상 미리 정렬된 데이터를 필요로 하므로 쿼리 출력은 창 함수의 / ORDER BY절 중 하나 또는 다른 항목에 따라 정렬됩니다 . 그러나 이것에 의존하는 것은 권장되지 않습니다. ORDER BY결과가 특정 방식으로 정렬되도록 하려면 명시적 최상위 절을 사용하십시오.

'Postgresql_DB_가이드' 카테고리의 다른 글

목록 선택  (0) 2022.08.06
쿼리 개요  (0) 2022.08.06
수정된 행에서 데이터 반환  (0) 2022.08.06
데이터 업데이트  (0) 2022.08.06
데이터 삽입  (0) 2022.08.06