교차 조인의 용도는 무엇입니까?


105

교차 조인은 두 세트의 튜플에서 데카르트 곱을 수행합니다.

SELECT *
FROM Table1
CROSS JOIN Table2

어떤 상황에서 그러한 SQL 작업이 특히 유용합니까?


36
이 질문이 닫혀서 정말 슬프다. 커뮤니티 위키로 표시 될 수 있다고 생각하지만 건설적이지 않다고 말하는 것은 불공평합니다.
Wayne Koorts

1
나는 동의한다. 이것은 내가 가진 정확한 질문에 답했습니다.
Hades

10
초보 개발자가 사용중인 소프트웨어의 특정 기능이 갖는 의미를 이해하는 데 어려움을 겪는 경우가 있습니다. 이와 같은 질문은 신참 개발자에게 도움이되는 특수성입니다. 주로 다음 토론이 주니어 개발자가 고려하지 않은 많은 가능성을 조명하기 때문입니다. 질문의 형식은 기껏해야 기본적이지만 "왜 이것이 존재 하는가?"라는 질문을한다는 점에서 정직한 것처럼 보입니다. 나는 Wayne Koorts의 의견에 동의합니다. casperOne이 이것을 종결하기로 선택하고 "건설적이지 않음"이라고 불렀던 것은 부끄러운 일입니다. "건설적이지 않은"부분은 특히 나를 짜증나게합니다.
Kaorie

답변:


93

특정 의류 품목에 대한 크기 및 색상 정보와 같이 완전히 채우려는 "그리드"가있는 경우 :

select 
    size,
    color
from
    sizes CROSS JOIN colors

하루의 1 분마다 행이 포함 된 테이블을 원할 수 있으며이를 사용하여 프로 시저가 1 분마다 실행되었는지 확인하여 세 개의 테이블을 교차 할 수 있습니다.

select
    hour,
    minute
from
    hours CROSS JOIN minutes

또는 연중 매월 적용 할 표준 보고서 사양 세트가 있습니다.

select
    specId,
    month
from
    reports CROSS JOIN months

이들을 뷰로 유지하는 문제는 대부분의 경우 특히 옷과 관련하여 완전한 제품을 원하지 않는다는 것입니다. MINUS쿼리에 논리를 추가 하여 가지고 있지 않은 특정 조합을 제거 할 수 있지만 다른 방법으로 테이블을 채우고 카티 전 곱을 사용하지 않는 것이 더 쉬울 수 있습니다.

또한 생각보다 행이 몇 개 더 많거나 WHERE절이 부분적으로 또는 완전히 누락 된 테이블에서 교차 조인을 시도하게 될 수도 있습니다 . 이 경우 DBA는 누락 사실을 즉시 알려줄 것입니다. 보통 그 또는 그녀는 행복하지 않을 것입니다.


5
...이 경우 DBA는 누락 사실을 즉시 알려줄 것입니다. 보통 그 또는 그녀는 행복하지 않을 것입니다. ... 하하, 정말!
RSW 2013 년

2
@Dave : 두 번째 예는 1 시간 CROSS JOIN 분이 아닐까요?
Rakesh

@Rakesh, 좋은 캐치, 나는 내가 타이핑하는 것 이외의 것을 생각하고 있었다. 결정된.
Dave DuPlantis 2013 년

1
두 세트의 ID (아마도 csv 형식)가 주어지면 교차 조인이 매우 실용적이라고 상상할 수 있습니다. 한 세트에는 직원 ID가 포함되고 다른 세트에는 작업 ID가 포함됩니다. 아이디어는 EmployeeTask에 대한 M2M 테이블이 있다는 것입니다. 교차 조인을 사용하여 주어진 모든 작업을 주어진 모든 직원에게 할당 할 수 있으며 csv를 테이블 변수 (또는 무언가)로 변환 할 수 있습니다.
SynBiotik 2014 년


14

일반적으로 대부분의 데이터베이스 쿼리에 대해 전체 카티 전 곱을 원하지 않습니다. 관계형 데이터베이스의 전체적인 힘은 db에서 불필요한 행을 가져 오는 것을 방지하기 위해 관심이있는 모든 제한을 적용 할 수 있다는 것입니다.

저는 여러분이 원할 수있는 하나의 인위적인 예를 가정합니다. 직원 테이블과 일을해야하는 작업 테이블이 있고 한 직원이 하나의 작업에 할당 할 수있는 모든 할당을 확인하려는 경우입니다.


11

좋아요, 이것은 아마도 질문에 대답하지 않을 것입니다. 그러나 그것이 사실이라면 (그리고 나는 그것을 확신하지 못합니다) 그것은 재미있는 역사입니다.

Oracle 초기에 개발자 중 한 명이 테이블의 모든 행을 복제해야한다는 것을 깨달았습니다 (예 : 이벤트 테이블 일 수 있으며 "시작 이벤트"와 "종료 이벤트"를 별도로 변경해야 함). 항목). 그는 행이 두 개 뿐인 테이블이있는 경우 첫 번째 테이블의 열만 선택하여 크로스 조인을 수행 할 수 있다는 것을 깨달았습니다. 그래서 그는 자연스럽게 "DUAL"이라고 불리는 간단한 테이블을 만들었습니다.

나중에 작업 자체가 테이블과 관련이없는 경우에도 테이블에서 선택을 통해서만 수행 할 수있는 작업을 수행해야합니다 (아마도 시계를 잊고 SELECT SYSDATE FROM.를 통해 시간을 읽고 싶었을 것입니다. .) 그는 여전히 자신의 DUAL 테이블이 주변에 누워 있다는 것을 깨달았고 그것을 사용했습니다. 잠시 후 그는 시간이 두 번 인쇄되는 것을 보는 것에 지쳐 결국 행 중 하나를 삭제했습니다.

Oracle의 다른 사람들은 그의 테이블을 사용하기 시작했고 결국 표준 Oracle 설치에 포함하기로 결정했습니다.

하나의 행이 있다는 유일한 의미를 갖는 테이블이 "2"를 의미하는 이름을 갖는 이유를 설명합니다.


8

핵심은 "가능한 모든 조합 표시"입니다. 다른 계산 된 필드와 함께 사용하여 정렬 / 필터링했습니다.

예를 들어 차익 거래 (거래) 애플리케이션을 구축하고 있다고 가정합니다. 당신은 가격에 제품을 제공하는 판매자와 가격에 제품을 요구하는 구매자가 있습니다. 제품 키에 대해 교차 조인을 수행하고 (잠재적 인 구매자와 판매자를 일치시키기 위해) 비용과 가격 간의 스프레드를 계산 한 다음 desc를 정렬합니다. 이것은 당신 (중개자)에게 가장 수익성있는 거래를 실행하기 위해 제공합니다. 물론 거의 항상 다른 경계 필터 기준이 있습니다.


아! 이 설명이 가장 의미가 있습니다. 이 경우 여러 판매자가 동일한 상품을 판매 할 수 있기 때문에 상품 ID와 판매자 사이에 관계가 없기 때문에 INNER JOIN은 의미가 없습니다.
moonman239

3

숫자 0-9에 대해 10 개의 행이있는 숫자 테이블과 같은 것을 취합니다. 해당 테이블에 대해 교차 조인을 몇 번 사용하여 필요한 행 수에 상관없이 적절한 번호가 매겨진 결과를 얻을 수 있습니다. 이것은 많은 용도가 있습니다. 예를 들어,이 함수를 datadd () 함수와 결합하여 주어진 연도의 매일에 대한 집합을 얻을 수 있습니다.



1

특정 항목 및 날짜 조합 (가격, 재고 여부 등)에 대해 발행하려는 일련의 쿼리가 있다고 가정 해보십시오. 항목과 날짜를 별도의 임시 테이블에로드하고 쿼리가 테이블을 교차 조인하도록 할 수 있습니다. 특히 일부 데이터베이스는 IN 절의 요소 수를 제한하기 때문에 IN 절의 항목과 날짜를 열거하는 대안보다 더 편리 할 수 ​​있습니다.


1

당신은 그것을 사용할 수 있습니다 가입 CROSS 목적으로 테스트를위한 데이터를 생성 - - 모든 속성을 결합 - 당신이 예를 들어 혈액 그룹 (A, B, ...)의 모든 가능한 조합을 필요 Rh를 함께 - / +, 등등 ... :에 그것을 --tune 귀하의 목적을 위해;)-나는이 분야의 전문가가 아닙니다.)

CREATE TABLE "HR"."BL_GRP_01" 
("GR_1" VARCHAR2(5 BYTE));
REM INSERTING into BL_GRP_01
SET DEFINE OFF;
Insert into BL_GRP_02 (GR_1) values ('A');
Insert into BL_GRP_02 (GR_1) values ('B');
Insert into BL_GRP_02 (GR_1) values ('O');
Insert into BL_GRP_01 (GR_1) values (NULL);

CREATE TABLE "HR"."BL_GRP_02" 
("GR_1" VARCHAR2(5 BYTE));

REM INSERTING into BL_GRP_02
SET DEFINE OFF;
Insert into BL_GRP_02 (GR_1) values ('A');
Insert into BL_GRP_02 (GR_1) values ('B');
Insert into BL_GRP_02 (GR_1) values ('O');
Insert into BL_GRP_02 (GR_1) values (NULL);

CREATE TABLE "HR"."RH_VAL_01" 
("RH_VAL" VARCHAR2(5 BYTE));
REM INSERTING into RH_VAL_01
SET DEFINE OFF;
Insert into RH_VAL_01 (RH_VAL) values ('+');
Insert into RH_VAL_01 (RH_VAL) values ('-');
Insert into RH_VAL_01 (RH_VAL) values (NULL);

select distinct  a.GR_1 || b.GR_1 || c.RH_VAL as BL_GRP
from BL_GRP_01 a, BL_GRP_02 b, RH_VAL_01 c
GROUP BY a.GR_1, b.GR_1, c.RH_VAL;
  • 공통 ID가없는 2 개의 테이블에 대한 조인을 만든 다음 max () 등을 사용하여 그룹화하여 가능한 가장 높은 조합을 찾습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.