programing

INSER JOIN / LEFT JOIN 우선순위 및 그룹 강제 적용

bestcode 2023. 1. 1. 11:13
반응형

INSER JOIN / LEFT JOIN 우선순위 및 그룹 강제 적용

예를 들어 A, B1, B2, C1, C2 라고 합시다.

나는 A에서 선택하고 B1에 합류하고 B2에 합류한다.또한 C1의 A에서 선택하고 C2에 참여하고 있습니다.즉, 다음과 같습니다.

   SELECT *
     FROM A
     JOIN B1 ON A.b1 = B1.id
     JOIN B2 ON B1.b2 = B2.id
LEFT JOIN C1 ON A.c1 = C1.id
LEFT JOIN C2 ON C1.c2 = C2.id

B 브런치에 장애가 발생했을 경우 쿼리 전체가 실패했으면 합니다.이 경우 JOIN은 정상적으로 완료됩니다.

하지만 만약 'C'의 분기가 고장나면LEFT JOIN C2(이 경우 C1로부터의 정보는 필요 없습니다.NULLS를 원합니다)하지만 C 브런치가 실패해도 쿼리 전체가 성공하고 싶습니다.

그래서 필요한 건

    SELECT *
      FROM A
      JOIN B1 ON A.b1 = B1.id
      JOIN B2 ON B1.b2 = B2.id
 LEFT JOIN (C1 ON A.c1 = C1.id
       JOIN C2 ON C1.c2 = C2.id)

하지만 제가 아는 한 기존 구문과는 다릅니다.

현재 다음 중 하나로 구현하고 있습니다.

   SELECT *
     FROM A
     JOIN B1 ON A.b1 = B1.id
     JOIN B2 ON B1.b2 = B2.id
LEFT JOIN (SELECT *
             FROM C1
             JOIN C2 ON C1.c2 = C2.id) AS C ON A.c1 = C.c1

어느 쪽이든.

어떤 JOIN이 어떤 JOIN에 어울리는지, 어떤 JOIN의 우선 순위를 명확하게 표현할 수 있지만, 쓰기에는 무겁고 읽기에도 무겁고, 약간 장황합니다.

하지만 제가 놓친 또 다른 클린 솔루션이 있을까요?

테스트 세트:

DROP TABLE IF EXISTS A;
CREATE TABLE A (b1 int, c1 int);

DROP TABLE IF EXISTS B1;
CREATE TABLE B1 (id int, b2 int);

DROP TABLE IF EXISTS B2;
CREATE TABLE B2 (id int);

DROP TABLE IF EXISTS C1;
CREATE TABLE C1 (id int, c2 int);

DROP TABLE IF EXISTS C2;
CREATE TABLE C2 (id int);

INSERT INTO C2 VALUES (1), (2), (3); -- To remove to make join fail.
INSERT INTO C1 VALUES (1, 1), (2, 2), (3, 3);

INSERT INTO B2 VALUES (1), (2), (3);
INSERT INTO B1 VALUES (1, 1), (2, 2), (3, 3);

INSERT INTO A VALUES (1, 1), (2, 2), (3, 3);

괄호로 묶인 조인 구문은 다음과 같습니다.

SELECT *
  FROM A
  JOIN B1 ON A.b1 = B1.id
  JOIN B2 ON C1.b2 = B2.id
  LEFT JOIN 
   (C1 JOIN C2 ON C1.c2 = C2.id)
  ON A.c1 = C1.id

익숙한 산술 구문에서 괄호를 사용하는 방법을 생각해 보십시오.당신은 글을 쓰지 않을 것이다:

A * B1 * B2 (* C1 * C2)

다음과 같이 쓸 수 있습니다.

A * B1 * B2 * (C1 * C2)

즉, 곱셈 연산자는 이진 연산자이므로 왼쪽과 오른쪽의 두 개의 피연산자가 있습니다.피연산자는 항 또는 괄호로 둘러싸인 하위 표현식일 수 있습니다.그러나 하위 표현식은 동일한 규칙을 따라야 합니다. 곱셈은 여전히 이진 연산자입니다.식 왼쪽 끝에 이진 연산자를 붙일 수 없습니다.

제가 아는 한,

SELECT *
  FROM A
  INNER JOIN (B1,B2) 
     ON  A.b1 = B1.id
     AND C1.b2 = B2.id
  LEFT JOIN (C1,C2) 
     ON  A.c1 = C1.id
     AND C1.c2 = C2.id)

예상대로 작동하다

SELECT ... FROM (t1,t2) WHERE ... is the same as t1 INNER JOIN t2

위의 예시는 'INSER JOIN'처럼 기능하고 있습니다.CROSS JOIN이라는 사실에서는 조금 다릅니다만...지금까지 저는 진짜 차이를 이해하지 못했습니다.아마 누군가가 우리에게 말해줄 수 있을 것입니다.)

그때까지, obove의 예는 당신에게 효과가 있을 것입니다.

현재의 솔루션은 다음과 같은 뷰를 작성하는 것입니다.

CREATE OR REPLACE VIEW VC AS
SELECT C1.id AS c1_id, C2.id AS c2_id
  FROM C1
  JOIN C2 ON C1.c2 = C2.id;

왼쪽 연결만 하면 됩니다.

SELECT *
  FROM A
  JOIN B1 ON A.b1 = B1.id
  JOIN B2 ON B1.b2 = B2.id
  LEFT JOIN VC ON VC.c1_id = A.c1;

솔루션을 가독성 있게 유지하고 보기를 다른 쿼리에서 재사용할 수 있으므로 좋습니다.

언급URL : https://stackoverflow.com/questions/42813207/forcing-inner-join-left-join-precedence-and-groups

반응형