복붙노트

[SQL] 측면과 PostgreSQL에서 하위 쿼리의 차이점은 무엇입니까?

SQL

측면과 PostgreSQL에서 하위 쿼리의 차이점은 무엇입니까?

포스트 그레스는 측면이 결합 할 수있는 능력과 함께 나온 이후 나는 현재 복잡한 데이터가 전체 쿼리 또는 4 개 분 걸리고 비효율적 인 하위 쿼리를 많이 내 팀을 위해 덤프 않기 때문에, 나는 그것을 위로 읽어 봤는데.

나는 측면이 나를 도울 수 있습니다 조인 이해하지만 심지어 힙 분석에서이 같은 기사를 읽은 후, 나는 여전히 매우 따르지 않습니다.

조인 측면에 대한 사용 사례는 무엇입니까? 가입 측면의 차이와 하위 쿼리는 무엇인가?

해결법

  1. ==============================

    1.측면에 가입 (포스트 그레스 9.3 이상)보다 상관 하위 쿼리가 아닌 일반 서브 쿼리 같다. 단지 상관 하위 쿼리처럼 - -처럼 Andomar는 측면의 오른쪽에있는 함수 또는 하위 쿼리는 왼쪽 각 행에 대해 한 번 평가되어야 할 참여, 지적 일반 하위 쿼리 (테이블 식)를 한 번만 평가된다. (쿼리 플래너는하지만, 하나를위한 성능 최적화 할 수있는 방법이 있습니다.) 이 관련 대답이 같은 문제를 해결 나란히 양쪽에 대한 코드 예제가 있습니다 :

    측면에 가입 (포스트 그레스 9.3 이상)보다 상관 하위 쿼리가 아닌 일반 서브 쿼리 같다. 단지 상관 하위 쿼리처럼 - -처럼 Andomar는 측면의 오른쪽에있는 함수 또는 하위 쿼리는 왼쪽 각 행에 대해 한 번 평가되어야 할 참여, 지적 일반 하위 쿼리 (테이블 식)를 한 번만 평가된다. (쿼리 플래너는하지만, 하나를위한 성능 최적화 할 수있는 방법이 있습니다.) 이 관련 대답이 같은 문제를 해결 나란히 양쪽에 대한 코드 예제가 있습니다 :

    하나 이상의 열을 반환하는 경우, 측면 조인은 일반적으로, 간단 깨끗하고 빠릅니다. 또한, 상관 하위 쿼리에 해당이 남아있는 사실 ON ... 측면 가입 기억 :

    우리가 여기 답변에 넣어가는 무엇보다 신뢰할 수 :

    거기에이 할 수있는 가입 측면 것들입니다,하지만 (상관 관계) 하위 쿼리는 (쉽게) 할 수 없습니다. s 관 부질는 단일 값, 배수가 아닌 열 아닌 복수의 열을 반환 할 수 - 노출 된 함수 호출 (그들이 복수의 열을 반환하는 경우 다중 열을 발생하는)을 제외. 그러나 심지어 특정 집합을 돌려주는 기능 만 FROM 절에 사용할 수 있습니다. 포스트 그레스 9.4 이상에서 여러 매개 변수 () unnest처럼. 수동 :

    이 작품 그래서,하지만 쉽게 하위 쿼리로 대체 할 수 없습니다

    CREATE TABLE tbl (a1 int[], a2 int[]);
    SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2);  -- implicit LATERAL
    

    CROSS JOIN을 위해 FROM 절에 쉼표 (,) 짧은 표기법입니다. 측면은 테이블 함수에 대해 자동으로 가정한다. UNNEST 특별한 경우에 대한 자세한 (배열 식 [...])

    또한 직접 SELECT 목록에 unnest 같은 설정을 돌려주는 기능을 ()를 사용할 수 있습니다. 이 포스트 그레스 9.6까지 같은 SELECT 목록에서 하나 개 이상의 같은 기능을 가진 놀라운 행동을 전시하는 데 사용됩니다. 그러나 마침내 포스트 그레스 (10)로 소독 된과 (도하지 표준 SQL 경우) 현재 유효한 대안이있다. 보다:

    위의 예에서 건물 :

    SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
    FROM   tbl;
    

    비교:

    여기서 PG 9.6 위해 dbfiddle 여기 페이지 10 dbfiddle

    수동 :

    그래서이 두 쿼리는 (심지어 특히 유용하지 않은 경우) 유효합니다 :

    SELECT *
    FROM   tbl t
    LEFT   JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t ON TRUE;
    
    SELECT *
    FROM   tbl t, LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
    

    이 것은 아니지만 :

    SELECT *
    FROM   tbl t
    LEFT   JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;

    Andomar의 코드 예제 @ (십자가는이 조인 조건을 필요로하지 않는다 가입) 정확하고 아틸라의 IS @ 유효 이유입니다.

  2. ==============================

    2.비 측면과의 차이는 왼쪽 테이블의 행을 볼 수 있는지 여부에 거짓말을 가입 횡 방향. 예를 들면 :

    비 측면과의 차이는 왼쪽 테이블의 행을 볼 수 있는지 여부에 거짓말을 가입 횡 방향. 예를 들면 :

    select  *
    from    table1 t1
    cross join lateral
            (
            select  *
            from    t2
            where   t1.col1 = t2.col1 -- Only allowed because of lateral
            ) sub
    

    서브 쿼리가 가지고있는이 "외부보고"수단 번 이상 평가한다. 결국, t1.col1 많은 값을 가정 할 수있다.

    대조적으로, 비 - 횡 후 부질 한번 평가 될 수 조인

    select  *
    from    table1 t1
    cross join
            (
            select  *
            from    t2
            where   t2.col1 = 42 -- No reference to outer query
            ) sub
    

    횡없이 필요에 따라, 내부 질의는 질의 외부에 어떠한 방식으로 의존하지 않는다. 횡 쿼리 때문에 쿼리 자체 행 외부와의 관계, 상관 된 쿼리의 일례이다.

  3. ==============================

    3.첫째, 측면 및 크로스 같은 일입니다 적용합니다. 따라서 당신은 또한 크로스에 대해 읽을 수 있습니다 적용. 이 연령대에 SQL 서버에서 구현 되었기 때문에, 당신은 그 측면이에 대한 자세한 정보를 찾을 수 있습니다.

    첫째, 측면 및 크로스 같은 일입니다 적용합니다. 따라서 당신은 또한 크로스에 대해 읽을 수 있습니다 적용. 이 연령대에 SQL 서버에서 구현 되었기 때문에, 당신은 그 측면이에 대한 자세한 정보를 찾을 수 있습니다.

    둘째, 나의 이해에 따라, 당신은 하위 쿼리를 사용하는 대신 측면 사용 할 수 없어 아무것도 없다. 그러나:

    쿼리 다음과 같은 고려하십시오.

    Select A.*
    , (Select B.Column1 from B where B.Fk1 = A.PK and Limit 1)
    , (Select B.Column2 from B where B.Fk1 = A.PK and Limit 1)
    FROM A 
    

    이 상태에서 측면 사용할 수 있습니다.

    Select A.*
    , x.Column1
    , x.Column2
    FROM A LEFT JOIN LATERAL (
      Select B.Column1,B.Column2,B.Fk1 from B  Limit 1
    ) x ON X.Fk1 = A.PK
    

    이 쿼리에서는 인한 한계 절에 정상에 가입 할 수 없습니다. 조인 조건을 간단이 없을 ​​때 측면 또는 크로스 사용할 수 있습니다 적용합니다.

    이 적용 측면 또는 교차 더 많은 용도가 있지만 이것은 내가 찾은 가장 일반적인 하나입니다.

  4. ==============================

    4.아무도 지적하지 않았다 한가지는 모든 선택된 행에 사용자 정의 함수를 적용하는 측면 쿼리를 사용할 수 있다는 것입니다.

    아무도 지적하지 않았다 한가지는 모든 선택된 행에 사용자 정의 함수를 적용하는 측면 쿼리를 사용할 수 있다는 것입니다.

    예를 들어 :

    CREATE OR REPLACE FUNCTION delete_company(companyId varchar(255))
    RETURNS void AS $$
        BEGIN
            DELETE FROM company_settings WHERE "company_id"=company_id;
            DELETE FROM users WHERE "company_id"=companyId;
            DELETE FROM companies WHERE id=companyId;
        END; 
    $$ LANGUAGE plpgsql;
    
    SELECT * FROM (
        SELECT id, name, created_at FROM companies WHERE created_at < '2018-01-01'
    ) c, LATERAL delete_company(c.id);
    

    그건 내가 PostgreSQL의에서 이런 종류의 작업을 수행하는 방법을 알고있는 유일한 방법입니다.

  5. from https://stackoverflow.com/questions/28550679/what-is-the-difference-between-lateral-and-a-subquery-in-postgresql by cc-by-sa and MIT license