programing

SQL "Join" on null 값

goodcopy 2023. 6. 17. 22:48
반응형

SQL "Join" on null 값

통제할 수 없는 이유로 두 개의 테이블을 결합해야 하고 일치시킬 null 값이 필요합니다.내가 생각할 수 있는 가장 좋은 옵션은 UUID를 뱉어 내 비교 값으로 사용하는 것이었지만 보기 흉합니다.

SELECT * FROM T1 JOIN T2 ON nvl(T1.SOMECOL,'f44087d5935dccbda23f71f3e9beb491') = 
   nvl(T2.SOMECOL,'f44087d5935dccbda23f71f3e9beb491')

어떻게 하면 더 잘할 수 있을까요?이는 중요한 경우 Oracle에 적용되며, 사용자가 업로드한 데이터 배치를 기존 데이터 배치와 비교하여 일치하는 행이 있는지 확인해야 하는 애플리케이션입니다.돌이켜보면, 우리는 두 데이터 세트의 조인 열 중 어떤 것도 null을 포함하지 않도록 방지했어야 했지만, 그러지 않았고 이제 우리는 그것과 함께 살아야 합니다.

편집: 분명히 말씀드리자면, 저는 null에만 관심이 있는 것이 아닙니다.열이 null이 아닌 경우 실제 값과 일치하도록 합니다.

이 방법이 효과가 있을 수도 있지만 실제로 시도해 본 적은 없습니다.

SELECT * 
FROM T1 JOIN T2 
ON T1.SOMECOL = T2.SOMECOL OR (T1.SOMECOL IS NULL AND T2.SOMECOL IS NULL)

SQL Server에서 사용한 적이 있는 항목:

WHERE (a.col = b.col OR COALESCE(a.col, b.col) IS NULL)

분명히 OR 때문에 효율적이지 않지만 예약된 값이 없는 한 모호함이나 접힘 없이 양쪽에 NULL을 매핑할 수 있습니다. 이는 가능한 최선의 방법입니다(그리고 만약 있다면 NULL이 설계에 허용된 이유는 무엇입니까...).

에서는 null 값을 사용하여 할 수 .decode:

    SELECT * FROM T1 JOIN T2 ON DECODE(T1.SOMECOL, T2.SOMECOL, 1, 0) = 1

decode는 null을 동일하게 처리하므로 "숫자" 없이 작동합니다.두 열의 데이터 유형이 같아야 합니다.

가장 읽기 쉬운 코드는 만들 수 없지만 여전히 더 나은 것 같습니다.t1.id = t2.id or (t1.id is null and t2.id is null)

이러한 종류의 작업을 위해 Oracle은 내부적으로 문서화되지 않은 함수 sys_op_map_nonnull()을 사용합니다. 여기서 쿼리는 다음과 같습니다.

SELECT *
FROM T1 JOIN T2 ON sys_op_map_nonnull(T1.SOMECOL) = sys_op_map_nonnull(T2.SOMECOL)

문서화되어 있지 않으므로 이 경로로 이동할 경우 주의하십시오.

더 나은 방법은 없지만 현재 사용 중인 JOIN은 실제 "JOIN"을 수행하지 않습니다(T1.SOMECL과 T2.SOMECL은 둘 다 해당 열에 NULL 값을 가지고 있는 것 이외에는 상관 관계가 없습니다).기본적으로 NULL에 대한 JOIN을 사용하여 행이 일치하는지 확인할 수 없습니다.

NULL은 다른 NULL과 같지 않습니다.어떻게 가치를 알 수 없는 것이 가치를 알 수 없는 다른 것과 같을 수 있습니까?

단순하고 활용도가 높습니다.COALESCE첫 번째 를 반환합니다.

SELECT * FROM T1 JOIN T2 ON 
  COALESCE(T1.Field, 'magic string') = 
     COALESCE(T2.Field, 'magic string')

걱정해야 할 것은 '마법 문자열'이 두 테이블 모두에서 조인 필드의 법적 값에 포함될 수 없다는 것입니다.

아래 쿼리와 함께 사용해 볼 수 있습니다.

SELECT *
FROM TABLEA TA
JOIN TABLEB TB ON NVL(TA.COL1,0)=NVL(TB.COL2,0);

값이 null인 경우 테이블을 결합할 수 있습니까?조인 술어에서 가능한 null 값을 제외할 수는 없습니까?두 테이블의 행이 null 값으로 연관될 수 있다는 것을 이해하기 어렵습니다.table1.col_a에 100개의 null이 있고 table2.col_b에 100개의 null이 있으면 null이 있는 행에 대해서만 10000개의 행이 반환됩니다.틀리게 들립니다.

하지만, 당신은 그것이 필요하다고 말했습니다.문자 비교 비용이 상대적으로 많이 들기 때문에 null 열을 더 작은 문자열로 병합하는 것이 좋습니다.열의 데이터가 텍스트인 경우에는 null을 정수로 병합하는 것이 좋습니다.그러면 '비교' 속도가 매우 빨라져 기존 데이터와 충돌할 가능성이 거의 없습니다.

이것을 밖에 버리기만 하면 -- 이 널들을 빈 문자열처럼 알려진 값으로 통합할 수 있는 방법이 있을까요?테이블이 어떻게 배치되어 있는지 잘 모른다는 것은 당신이 그런 식으로 의미를 잃어버릴지 모른다는 것을 의미합니다. 즉, 빈 문자열은 "사용자가 전화 번호 입력을 거부했습니다"를 나타내고 NULL은 "우리는 그것에 대해 묻는 것을 잊었습니다" 또는 유사한 것을 의미합니까?

가능성은 높지 않지만, 가능하다면, 비교할 수 있는 가치가 있을 것이고 합법적인 가입을 얻을 수 있습니다.

양쪽 열에 Null이 있는지 확인하는 것과 동일하지 않습니까?

SELECT * FROM T1, T2 WHERE T1.SOMECOL IS NULL and T2.SOMECOL IS NULL

또는

SELECT * FROM T1 CROSS JOIN T2 WHERE T1.SOMECOL IS NULL and T2.SOMECOL IS NULL

왜 그런 것이 아닙니다.

NVL(T1)의 T1 연결 T2에서 *를 선택합니다.SOMECOL, 'null') = nvl(T2).SOMECOL, 'null')

나는 당신이 왜 UUID를 사용하는지 모르겠습니다.예를 들어, 메모리 공간을 줄이기 위해 "null" 문자열과 같이 열에 없는 문자열을 사용할 수 있습니다. 그고이를이해결책한용리▁using▁solution해▁and▁the책그리.nvl는 사하는솔훨빠씬릅다니다를 빠릅니다.or ... is null예를 들어, 에릭 페트로엘제에 의해 제안되었습니다.

가입을 위해 여전히 nvl()을 사용할 수 있다고 생각합니다.

SELECT *
FROM T1
JOIN T2 ON NVL(T2.COL1,-1)=NVL(T1.COL1,-1);

그러나 col1 열에 함수 기반 인덱스를 추가해야 합니다.

CREATE INDEX IND_1 ON T1 (NVL(COL1,-1));
CREATE INDEX IND_2 ON T2 (NVL(COL1,-1));

인덱스는 NVL(...)의 조인 속도를 크게 향상시켜야 합니다.

@사라트 아바나부

이것은 최선의 접근법이 아닙니다.TA.COL1이 값 0을 유지하고 TB.COL2가 NULL이면 해당 레코드에 가입합니다. 이는 올바르지 않습니다.

SELECT *
FROM TABLEA TA
JOIN TABLEB TB ON NVL(TA.COL1,0)=NVL(TB.COL2,0);

CASE를 사용하여 하위 쿼리의 null 값을 바꾼 다음 결과에 참여할 수도 있습니다.

SELECT T1.COL1 FROM
(
   (SELECT (CASE WHEN COL1 IS NULL THEN 'X' ELSE COL1 END) AS COL1 FROM TABLE1) T1
   JOIN
   (SELECT (CASE WHEN COL1 IS NULL THEN 'X' ELSE COL1 END) AS COL1 FROM TABLE2) T2
)
ON T1.COL1=T2.COL1

언급URL : https://stackoverflow.com/questions/1758409/sql-join-on-null-values

반응형