PostgreSQL에서 가로 조인과 하위 쿼리의 차이점은 무엇입니까?
포스트그레 이후SQL은 다음과 같은 기능을 제공합니다.LATERAL
조인스, 저는 현재 팀을 위해 전체 쿼리에 4분 이상 걸리는 비효율적인 하위 쿼리가 많은 복잡한 데이터 덤프를 수행하고 있기 때문에 이에 대해 자세히 읽어보고 있습니다.
는 그것을 합니다.LATERAL
조인스가 도움이 될 수도 있지만, 힙 분석에서 이와 같은 기사를 읽은 후에도 여전히 잘 이해하지 못합니다.
의 사용 사례는 무엇입니까?LATERAL
가입하시겠습니까? A의 차이점은 무엇입니까?LATERAL
가입과 하위 질의?
의 개요LATERAL
가입하시겠습니까?
이 기능은 Postgre와 함께 도입되었습니다.SQL 9.3.설명서:
하쿼리표에 나타나는 하위
FROM
키워드 앞에 올 수 있습니다.LATERAL
앞에 있는 통해이제공열참수있에서 하는 할 수 .FROM
(. (미목함항포미)LATERAL
는 독립적으로 와 상호 할 수 .FROM
항목으)로 됩니다.함수는 함다표음시다니됩에는수에 됩니다.
FROM
또한 키워드 앞에 올 수 있습니다.LATERAL
사항입니다.의 " 나함의수경키선는워드사택다니항입우그러▁▁preceding▁다▁by사선니입항▁contain▁the"에서 제공하는 열에 가 포함될 수 있습니다. 함수의 인수는 이전에 제공된 열에 대한 참조를 포함할 수 있습니다.FROM
어떤 경우에도 항목
여기에는 기본 코드 예제가 나와 있습니다.
상관된 하위 쿼리에 더 가깝습니다.
A LATERAL
조인은 일반 하위 쿼리가 아니라 상관된 하위 쿼리에 더 가깝습니다. 그 표현식은 a의 오른쪽에 있습니다.LATERAL
조인은 상관된 하위 쿼리와 마찬가지로 각 행에 대해 한 번씩 평가되는 반면 일반 하위 쿼리(테이블 표현식)는 한 번만 평가됩니다. (하지만 쿼리 플래너는 성능을 최적화하는 방법이 있습니다.)
동일한 문제를 해결하는 코드 예제가 나란히 있는 관련 답변:
둘 이상의 열을 반환하는 경우, aLATERAL
조인은 일반적으로 더 단순하고, 더 깨끗하고, 더 빠릅니다.
또한 상관된 하위 쿼리의 등가물은 다음과 같습니다.
하위 쿼리에서 수행할 수 없는 작업
어떤 것들이 있습니다.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()
에 시대에SELECT
직접 열거하다이것은 같은 기능에서 하나 이상의 놀라운 행동을 보여주곤 했습니다.SELECT
Postgres 9.6까지 나열합니다.그러나 Postgres 10을 사용하여 최종적으로 삭제되었으며 이제는 표준 SQL이 아니더라도 유효한 대안이 되었습니다.참조:
위의 예를 기반으로 구축:
SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM tbl;
비교:
페이지 9.6에 대한 dbfidle 여기.
여기 페이지 10에 대한 dbfiddle.
잘못된 정보를 명확히 합니다.
의
INNER
그리고.OUTER
유형, 조인 지정해야 . 즉, 조인 조건은 "", "", "" 중 입니다.NATURAL
,ON
join_condition, 또는USING
(vmdk_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;
그래서 안도마르의 코드 예제가 맞는 것입니다.CROSS JOIN
가입 조건이 필요하지 않음) 및 아틸라의 이라 그렇지 않았습니다.
의 lateral
a 리고a.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
쿼리 자체 외부의 행과의 관계로 인해 쿼리를 실행할 수 있습니다.
데이터베이스 테이블
과 같은 다을갖것을 갖는 것.blog
플랫폼에서 호스팅하는 블로그를 저장하는 데이터베이스 테이블:
또한 현재 두 개의 블로그를 호스팅하고 있습니다.
이드 | 생성된 | 제목 | URL |
---|---|---|---|
1 | 2013-09-30 | 블라드 미할체아의 블로그 | https://vladmihalcea.com |
2 | 2017-01-22 | 과민증 | https://hypersistence.io |
SQL RATAL JOIN을 사용하지 않고 보고서 가져오기
다음 데이터를 추출하는 보고서를 작성해야 합니다.blog
테이블:
- 블로그 아이디
- 블로그 시대(년 단위)
- 다음 블로그 기념일 날짜
- 다음 기념일까지 남은 일수
Postgre를 사용하는 경우SQL을 실행한 후 다음 SQL 쿼리를 실행해야 합니다.
SELECT
b.id as blog_id,
extract(
YEAR FROM age(now(), b.created_on)
) AS age_in_years,
date(
created_on + (
extract(YEAR FROM age(now(), b.created_on)) + 1
) * interval '1 year'
) AS next_anniversary,
date(
created_on + (
extract(YEAR FROM age(now(), b.created_on)) + 1
) * interval '1 year'
) - date(now()) AS days_to_next_anniversary
FROM blog b
ORDER BY blog_id
보다시피,피시▁the▁as다보,.age_in_years
▁the▁you▁calcul▁has다합을 계산할 때 하기 때문에 세 번 .next_anniversary
그리고.days_to_next_anniversary
가치.
그리고, 바로 거기서 수평 결합이 우리를 도울 수 있습니다.
SQL RATAL JOIN을 사용하여 보고서 가져오기
은 다음관데시다지다니합원음을 합니다.LATERAL JOIN
구문:
- 12c 이후 Oracle
- 9.3 이후 PostgreSQL
- 8.0.14 이후의 MySQL
는 SQL Server 다을이할수있다니습을 수 .LATERAL JOIN
용사를 CROSS APPLY
그리고.OUTER APPLY
.
측면 결합을 통해 다음을 재사용할 수 있습니다.age_in_years
는 값을 매기고 더 .next_anniversary
그리고.days_to_next_anniversary
가치.
다음과 같이 이전 쿼리를 다시 작성하여 가로 조인을 사용할 수 있습니다.
SELECT
b.id as blog_id,
age_in_years,
date(
created_on + (age_in_years + 1) * interval '1 year'
) AS next_anniversary,
date(
created_on + (age_in_years + 1) * interval '1 year'
) - date(now()) AS days_to_next_anniversary
FROM blog b
CROSS JOIN LATERAL (
SELECT
cast(
extract(YEAR FROM age(now(), b.created_on)) AS int
) AS age_in_years
) AS t
ORDER BY blog_id
리고그.age_in_years
하여 재사용할 수 있습니다.next_anniversary
그리고.days_to_next_anniversary
계산:
blog_id | 나이[나이] | 차기의 | 다음 기념일까지 |
---|---|---|---|
1 | 7 | 2021-09-30 | 295 |
2 | 3 | 2021-01-22 | 44 |
훨씬 낫죠?
그age_in_years
는 의모 기계다니됩산대해에의 됩니다.blog
테이블. 즉, 상관된 하위 쿼리처럼 작동하지만 하위 쿼리 레코드는 기본 테이블과 결합되므로 하위 쿼리에서 생성된 열을 참조할 수 있습니다.
첫째, 가로 방향과 가로 방향 적용은 동일합니다.따라서 교차 적용에 대해서도 읽을 수 있습니다.SQL Server에서 오랫동안 구현되었기 때문에 Rateral보다 자세한 정보를 확인할 수 있습니다.
둘째, 제가 알기로는 횡문법을 사용하는 대신 서브쿼리를 사용하여 할 수 없는 것이 없습니다.그러나:
다음 쿼리를 고려해 보십시오.
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
쿼리를 사용하여 선택한 모든 행에 사용자 정의 함수를 적용합니다.
예를 들어:
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);
그게 내가 포스트그레에서 이런 일을 하는 방법을 아는 유일한 방법입니다.SQL.
언급URL : https://stackoverflow.com/questions/28550679/what-is-the-difference-between-a-lateral-join-and-a-subquery-in-postgresql
'programing' 카테고리의 다른 글
날짜 시간 대 날짜 시간 오프셋 (0) | 2023.05.08 |
---|---|
디렉터리를 반복적으로 순환하여 특정 확장명의 파일을 삭제하는 방법 (0) | 2023.05.08 |
Postgre용 GUI 도구SQL (0) | 2023.05.08 |
문자열 구분 기호로 문자열을 분할하려면 어떻게 해야 합니까? (0) | 2023.05.08 |
이클립스에서 코드 블록을 축소하는 방법은 무엇입니까? (0) | 2023.05.08 |