programing

다른 테이블에 조건이 있는 테이블의 왼쪽 조인

codeshow 2023. 8. 20. 12:55
반응형

다른 테이블에 조건이 있는 테이블의 왼쪽 조인

나는 여러 테이블에 참여하고 두 번째 테이블에 참여할 때 세 번째 테이블에 조항을 두려고 합니다.저는 where 절을 사용해 보았지만 두 번째 테이블의 열을 무효화하고 싶을 때 전체 결과에 적용됩니다.

예를 들어, 그것은 더 명확해질 것입니다.나는 4개의 테이블이 있습니다.

CREATE TABLE A (ID INTEGER PRIMARY KEY);
CREATE TABLE B (ID INTEGER PRIMARY KEY, A_ID INTEGER, C_ID INTEGER, D_ID INTEGER);
CREATE TABLE C (ID INTEGER PRIMARY KEY, CONDITIONS INTEGER);
CREATE TABLE D (ID INTEGER PRIMARY KEY, CONDITIONS INTEGER);

테이블 B가 테이블 A를 테이블 C와 D에 연결합니다.

샘플 데이터는 다음과 같습니다.

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

INSERT INTO C VALUES (1, 1);
INSERT INTO C VALUES (2, 1);
INSERT INTO C VALUES (3, 0);

INSERT INTO D VALUES (1, 0);
INSERT INTO D VALUES (2, 0);

INSERT INTO B VALUES (1, 1, 1, NULL);
INSERT INTO B VALUES (2, 1, 2, NULL);
INSERT INTO B VALUES (3, 1, 3, NULL);
INSERT INTO B VALUES (4, 2, NULL, 1);
INSERT INTO B VALUES (5, 2, NULL, 2);

왼쪽으로 직접 조인:

SELECT A.ID, B.ID, C.ID, D.ID 
FROM A 
LEFT JOIN B ON B.A_ID = A.ID 
LEFT JOIN C ON B.C_ID = C.ID 
LEFT JOIN D ON B.D_ID = D.ID;

데이터를 반환합니다.

╔══════╦══════╦══════╦══════╗
║ A.id ║ B.id ║ C.id ║ D.id ║
╠══════╬══════╬══════╬══════╣
║   1  ║   1  ║   1  ║ null ║
║   1  ║   2  ║   2  ║ null ║
║   1  ║   3  ║   3  ║ null ║
║   2  ║   4  ║ null ║   1  ║
║   2  ║   5  ║ null ║   2  ║
║   3  ║ null ║ null ║ null ║
╚══════╩══════╩══════╩══════╝

제가 하려는 것은 C 테이블과 D 테이블의 데이터로 B 테이블을 필터링하는 것입니다.요청에 단순히 where 조건을 추가하는 경우:

SELECT A.ID, B.ID, C.ID, D.ID 
FROM A 
LEFT JOIN B ON B.A_ID = A.ID 
LEFT JOIN C ON B.C_ID = C.ID 
LEFT JOIN D ON B.D_ID = D.ID 
WHERE (C.ID IS NULL OR C.CONDITIONS = 1)
AND (D.ID IS NULL OR D.CONDITIONS = 1);

반환되는 항목:

╔══════╦══════╦══════╦══════╗
║ A.id ║ B.id ║ C.id ║ D.id ║
╠══════╬══════╬══════╬══════╣
║   1  ║   1  ║   1  ║ null ║
║   1  ║   2  ║   2  ║ null ║
║   3  ║ null ║ null ║ null ║
╚══════╩══════╩══════╩══════╝

그건 논리적이지만 내가 원하는 것은 아닙니다.제가 원하는 것은:

╔══════╦══════╦══════╦══════╗
║ A.id ║ B.id ║ C.id ║ D.id ║
╠══════╬══════╬══════╬══════╣
║   1  ║   1  ║   1  ║ null ║
║   1  ║   2  ║   2  ║ null ║
║   2  ║ null ║ null ║ null ║
║   3  ║ null ║ null ║ null ║
╚══════╩══════╩══════╩══════╝

그것은 그들과 계속 어울립니다.A.ID = 2그러나 C와 D의 일치 조건을 가진 B 값을 찾을 수 없습니다.

나는 조건을 넣으려고 노력했습니다.ONC 및 D 테이블에 결합하는 절이지만 B에서 데이터는 데이터를 유지합니다.

╔══════╦══════╦══════╦══════╗
║ A.id ║ B.id ║ C.id ║ D.id ║
╠══════╬══════╬══════╬══════╣
║   1  ║   1  ║   1  ║ null ║
║   1  ║   2  ║   2  ║ null ║
║   1  ║   3  ║ null ║ null ║
║   2  ║   4  ║ null ║ null ║
║   2  ║   5  ║ null ║ null ║
║   3  ║ null ║ null ║ null ║
╚══════╩══════╩══════╩══════╝

저는 이제 그 묘기를 부릴 생각이 없습니다.

당신이 해야 할 일은 왼쪽 외측 접합입니다.b의 테이블.c그리고.d테이블 먼저, 그리고 나서 바깥쪽은 그것을 다시 연결합니다.a표 값이 다음 중 하나에 존재하는 경우c또는d조건 열.이와 같은 경우:

SELECT a.id a_id, b2.b_id, b2.c_id, b2.d_id
FROM   a
       LEFT OUTER JOIN (SELECT b.id b_id,
                               b.a_id,
                               c.id c_id,
                               d.id d_id
                        FROM   b
                               LEFT OUTER JOIN c ON b.c_id = c.id AND c.conditions = 1
                               LEFT OUTER JOIN d ON b.d_id = d.id AND d.conditions = 1) b2
         ON a.id = b2.a_id AND COALESCE(b2.c_id, b2.d_id) IS NOT NULL
ORDER BY a.id, b2.b_id, b2.c_id, b2.d_id;

      A_ID       B_ID       C_ID       D_ID
---------- ---------- ---------- ----------
         1          1          1 
         1          2          2 
         2                       
         3                       

(편집된 출력물에서 문제를 발견해 준 Alex Pool에게 감사드립니다!)


ETA:

이는 다음과 같이 기록될 수도 있습니다.

SELECT a.id a_id, b.id b_id, c.id c_id, d.id d_id
FROM   a
       LEFT OUTER JOIN (b
                        LEFT OUTER JOIN c ON b.c_id = c.id AND c.conditions = 1
                        LEFT OUTER JOIN d ON b.d_id = d.id AND d.conditions = 1)
         ON a.id = b.a_id AND COALESCE(c.id, d.id) IS NOT NULL
ORDER BY a.id, b.id, b.c_id, b.d_id;

이는 더 간단하지만 잠재적으로 의도를 해독하기가 더 어렵습니다(따라서 향후 유지 관리가 더 어렵습니다).이것이 유효한 구문인지 전혀 몰랐기 때문에 여기에 추가했습니다. 그러면 더 잘 작동한다고 느낄 수 있습니다.

제가 이전 것을 틀린 것으로 삭제했기 때문에 다른 답변을 추가합니다.저는 이것이 올바른 논리라고 생각합니다.

SELECT A.ID, B.ID, C.ID, D.ID 
FROM A LEFT JOIN
     (B LEFT JOIN
      C
      ON B.C_ID = C.ID AND C.CONDITIONS = 1 LEFT JOIN
      D
      ON B.D_ID = D.ID AND D.CONDITIONS = 1
     )
     ON B.A_ID = A.ID AND
        (C.ID IS NOT NULL OR D.ID IS NOT NULL);

이것은 제가 테스트했을 때 정확한 결과를 반환합니다.

그것은 흥미로운 문제입니다.이 아이디어는 괄호를 사용하여 비교를 "지연"하는 것입니다.A그리고.B이를 통해 조건이 일치하는지 여부도 판단할 수 있습니다.C또는D.

사실 나는 하위 쿼리로 그것을 하는 다른 방법을 찾았습니다.ON절:

SELECT A.ID, B.ID, C.ID, D.ID 
FROM A 
LEFT JOIN B ON B.A_ID = A.ID 
    AND (B.C_ID IS NULL OR B.ID IN (SELECT B.ID FROM B JOIN C ON C.ID = B.C_ID AND C.CONDITIONS = 1)
    AND (B.D_ID IS NULL OR B.ID IN (SELECT B.ID FROM B JOIN D ON D.ID = B.D_ID AND D.CONDITIONS = 1)
LEFT JOIN C ON B.C_ID = C.ID 
LEFT JOIN D ON B.D_ID = D.ID;

어떤 솔루션이 A 테이블과 B, C, D 테이블에 다른 조항이 있으면 더 잘 수행될지 모르겠습니다.

언급URL : https://stackoverflow.com/questions/42972753/left-join-on-a-table-with-condition-on-others-table

반응형