답변:
A는 LATERAL
(포스트 그레스 9.3 이상)이 더 같은 조인 상관 하위 쿼리 가 아닌 일반 서브 쿼리. 마찬가지로 Andomar 지적 A는 오른쪽에, 함수 또는 하위 쿼리를 LATERAL
단지처럼 - 그것의 왼쪽 각 행에 대해 한 번 평가되어야 할 참여 상관 하위 쿼리 - 일반 하위 쿼리 (테이블 식)이 평가되는 동안 한 번 만. 쿼리 플래너는 성능을 최적화 할 수있는 방법
이 있습니다 . 이 관련 답변에는 동일한 문제를 해결하는 코드 예제가 나란히 있습니다.
복귀를 들어 하나 이상의 열을 , A는 LATERAL
가입 일반적으로, 간단 깨끗하고 빠릅니다.
또한 상관 된 하위 쿼리와 동등한 내용은 다음과 같습니다 LEFT JOIN LATERAL ... ON true
.
LATERAL
우리가 여기에 대답 할 것보다 권위가 있습니다.
가 있습니다 A는 것들 LATERAL
할 수있는 참여는하지만 (상관 관계) 하위 쿼리는 (쉽게) 할 수 없습니다. 상관 서브 쿼리는 베어 함수 호출 (여러 행을 리턴하면 결과 행을 곱함)을 제외하고 여러 열이 아니라 단일 행만 리턴 할 수 있습니다. 그러나 특정 반환 함수조차도 FROM
절 에서만 허용됩니다 . unnest()
Postgres 9.4 이상의 여러 매개 변수 와 유사합니다 .매뉴얼 :
이것은 오직
FROM
조항 .
따라서 이것은 작동하지만 하위 쿼리로 쉽게 바꿀 수는 없습니다.
CREATE TABLE tbl (a1 int[], a2 int[]);
SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2); -- implicit LATERAL
절의 쉼표 ( ,
) FROM
는의 짧은 표기법입니다 CROSS JOIN
.
LATERAL
테이블 함수에 대해 자동으로 가정됩니다.
특별한 경우에 대한 자세한 내용 UNNEST( array_expression [, ... ] )
:
SELECT
리스트의리스트 unnest()
에서 와 같이 set-returning 기능을 SELECT
직접 사용할 수도 있습니다. 이것은 동일한 SELECT
목록에서 Postgres 9.6까지 하나 이상의 이러한 기능으로 놀라운 동작을 나타 냈습니다. 그러나 마침내 Postgres 10으로 위생 처리되었으며 현재 표준 SQL이 아니더라도 유효한 대안입니다. 보다:
위의 예를 바탕으로 :
SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM tbl;
비교:
pg 9.6 용 dbfiddle 여기서
pg 10 용 dbfiddle 여기
들어
INNER
와OUTER
참여 유형 A는 조건, 즉, 정확히 하나를 지정해야 가입NATURAL
,ON
join_condition 또는USING
( join_column를 [...]). 의미는 아래를 참조하십시오.
의CROSS JOIN
경우이 절 중 어느 것도 나타날 수 없습니다.
따라서이 두 쿼리는 유효합니다 (특히 유용하지는 않지만).
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의 @ 코드 예제 정확합니다 (이 CROSS JOIN
A가 조인 조건을 필요로하지 않습니다)와 아틸라의 @ IS 잘못되었습니다.
LATERAL
하위 쿼리 에서 창 함수를 보여주는 또 다른 답변을 추가했습니다 . gis.stackexchange.com/a/230070/7244
비의 차이 lateral
와는 lateral
당신이 왼쪽 테이블의 행을 볼 수 있는지 여부에 거짓말을 가입 할 수 있습니다. 예를 들면 다음과 같습니다.
select *
from table1 t1
cross join lateral
(
select *
from t2
where t1.col1 = t2.col1 -- Only allowed because of lateral
) sub
이 "외형"은 하위 쿼리가 두 번 이상 평가되어야 함을 의미합니다. 결국 t1.col1
많은 값을 가정 할 수 있습니다.
반대로 lateral
조인 이 아닌 이후의 하위 쿼리 는 한 번만 평가할 수 있습니다.
select *
from table1 t1
cross join
(
select *
from t2
where t2.col1 = 42 -- No reference to outer query
) sub
없이 필요한 lateral
경우 내부 쿼리는 외부 쿼리에 의존하지 않습니다. lateral
검색어에의 일례이다 correlated
때문에 쿼리 자체 행 외부와의 관계, 쿼리.
select * from table1 left join t2 using (col1)
비교합니까? / on 조건을 사용하는 조인이 충분하지 않고 측면을 사용하는 것이 더 합리적 인 경우 분명하지 않습니다.
먼저, 측면 및 교차 적용은 동일합니다. 합니다. 따라서 Cross Apply에 대해서도 읽을 수 있습니다. SQL Server에서 오랫동안 구현되었으므로 Lateral에 대한 자세한 정보를 찾을 수 있습니다.
둘째, 내 이해에 따르면 측면을 사용하는 대신 하위 쿼리를 사용하여 수행 할 수있는 것은 없습니다. 그러나:
다음 쿼리를 고려하십시오.
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
이 쿼리에서는 limit 절로 인해 일반 조인을 사용할 수 없습니다. 측면 또는 교차 적용을 사용할 수 있습니다간단한 결합 조건이없는 경우 .
측면 또는 교차 적용에 대한 사용법이 더 있지만 이것이 내가 찾은 가장 일반적인 것입니다.
lateral
대신을 사용하는지 궁금합니다 apply
. 아마도 마이크로 소프트는이 구문을 특허 했습니까?
lateral
는 SQL 표준에 있지만 apply
그렇지 않습니다.
LEFT JOIN
조인 조건 이 필요합니다. ON TRUE
어떻게 든 제한하고 싶지 않다면 확인하십시오 .
cross join
또는 on
조건 을 사용하지 않으면 오류가 발생 합니다
아무도 지적하지 않은 것은 LATERAL
쿼리를 사용 하여 선택한 모든 행에 사용자 정의 함수를 적용 할 수 있다는 것 입니다.
예를 들어 :
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에서 이런 종류의 작업을 수행하는 방법을 아는 유일한 방법입니다.
apply
와 동일한lateral
SQL 표준에서)