13.2.9.2 JOIN 구문
MySQL은 SELECT
문과 여러 테이블의 DELETE
및 UPDATE
문 table_references
부분에 다음 JOIN
구문을 지원합니다.
table_references :
escaped_table_reference
[,escaped_table_reference
] ...escaped_table_reference
:table_reference
| {OJtable_reference
}table_reference
:table_factor
|join_table
table_factor
:tbl_name
[PARTITION (partition_names
) [AS]alias
] [index_hint_list
] |table_subquery
[AS]alias
| (table_references
)join_table
:table_reference
[INNER | CROSS] JOINtable_factor
[join_condition
] |table_reference
STRAIGHT_JOINtable_factor
|table_reference
STRAIGHT_JOINtable_factor
ONconditional_expr
|table_reference
{LEFT | RIGHT} [OUTER] JOINtable_reference
join_condition
|table_reference
NATURAL [{LEFT | RIGHT} [OUTER] JOINtable_factor
join_condition
: ONconditional_expr
| USING (column_list
)index_hint_list
:index_hint
[,index_hint
] ...index_hint
: USE {INDEX | KEY} [FOR {JOIN | ORDER BY | GROUP BY} ([index_list
) | IGNORE {INDEX | KEY} [FOR {JOIN | ORDER BY | GROUP BY} (index_list
) | FORCE {INDEX | KEY} [FOR {JOIN | ORDER BY | GROUP BY} (index_list
)index_list
:index_name
[,index_name
] ...
테이블 참조는 결합 식이라고도합니다.
MySQL 5.6.2 이후에서는 테이블 참조 (분할 된 테이블을 참조하는 경우)에는 파티션 서브 파티션 또는 둘 다의 쉼표로 구분 된 목록을 포함 PARTITION
옵션을 포함 할 수 있습니다. 이 옵션은 테이블 이름 뒤에이면서 별칭 선언 (존재하는 경우) 전에 지정됩니다. 이 옵션의 효과는 나열되어있는 파티션 또는 서브 파티션에서만 행이 선택되는 것입니다. 즉, 그 목록에 지정되지 않은 파티션 또는 서브 파티션은 모두 무시됩니다. 자세한 내용은 섹션 19.5 "파티션 선택" 을 참조하십시오.
table_factor
구문은 SQL 표준에 비해 확장되고 있습니다. 후자는 table_reference
만을 허용 괄호 안에 그 목록은 접수하지 않습니다.
이것은 table_reference
항목 목록의 각 쉼표를 내부 조인과 동등하게 보는 경우 보수적 인 확장입니다. 예 :
SELECT * FROM t1 LEFT JOIN (t2, t3, t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)
다음과 같습니다.
SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ON (t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)
MySQL에서는 JOIN
, CROSS JOIN
및 INNER JOIN
구문에 해당합니다 (서로 대체 할 수 있습니다). 표준 SQL에서는 그들은 동등하지 않습니다. INNER JOIN
은 ON
절과 함께 사용되어 CROSS JOIN
은 그렇지 때 사용됩니다.
일반적으로 내부 조인 연산만을 포함 조인 식의 괄호는 무시할 수 있습니다. MySQL은 또한 중첩 된 결합도 지원하고 있습니다 ( 섹션 8.2.1.11 "중첩 된 결합의 최적화" 를 참조하십시오).
인덱스 힌트를 지정하면 MySQL 최적화 프로그램이 인덱스를 사용하는 방법에 영향을 미칠 수 있습니다. 자세한 내용은 섹션 13.2.9.3 "인덱스 힌트 구문" 을 참조하십시오.
다음 목록은 결합을 작성할 때 고려해야 할 일반적인 요인에 대해 설명하고 있습니다.
테이블 참조는
또는tbl_name
ASalias_name
tbl_name alias_name
을 사용하여 별칭을 지정할 수 있습니다.SELECT t1.name, t2.salary FROM employee AS t1 INNER JOIN info AS t2 ON t1.name = t2.name; SELECT t1.name, t2.salary FROM employee t1 INNER JOIN info t2 ON t1.name = t2.name;
table_subquery
는FROM
절의 서브 쿼리라고도합니다. 서브 쿼리 결과에 테이블 이름을 지정하려면이 같은 서브 쿼리에 별칭을 포함해야합니다. 간단한 예를 보여줍니다. 섹션 13.2.10.8 "FROM 절의 서브 쿼리" 를 참조하십시오.SELECT * FROM (SELECT 1, 2, 3) AS t1;
조인 조건이 존재하지 않는 경우
INNER JOIN
과,
(쉼표)은 의미 적으로 동등합니다. 모두 지정된 테이블 사이의 데카르트를 생성합니다 (즉, 첫 번째 테이블의 모든 행은 두 번째 테이블의 모든 행과 조인됩니다).그러나 쉼표 연산자의 우선 순위는
INNER JOIN
,CROSS JOIN
,LEFT JOIN
등의 우선 순위보다 낮습니다. 조인 조건이있는 경우에 쉼표 결합을 다른 결합 형과 혼합시킨 경우「Unknown column '
라는 형식의 오류가 발생할 수 있습니다. 이 문제에 대한 대처에 관한 정보는이 섹션의 뒤 쪽에서 제공합니다.col_name
'col_name' in 'on clause'」ON
과 함께 사용되는conditional_expr
은WHERE
절에서 사용할 수있는 형식의 임의의 조건식입니다. 일반적으로 테이블의 결합 방법을 지정하는 조건은ON
절을 또한 결과 집합에 필요한 행을 제한하려면WHERE
절을 사용하십시오.LEFT JOIN
의ON
또는USING
부분에서 오른쪽 테이블에 일치하는 행이없는 경우 모든 컬럼이NULL
로 설정된 레코드가 오른쪽 테이블에 사용됩니다. 이 것을 사용하여 다른 테이블에 해당하는 행이 존재하지 않는 테이블에서 행을 검색 할 수 있습니다.SELECT left_tbl * FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;
이 예에서는
right_tbl
에 존재하지 않는id
값을 가지는left_tbl
의 모든 행 (즉,right_tbl
에 해당하는 행이없는left_tbl
의 모든 행)를 검색합니다. 이것은right_tbl.id
이NOT NULL
로 선언되어있는 것을 전제로하고 있습니다. 섹션 8.2.1.9 "LEFT JOIN과 RIGHT JOIN 최적화" 를 참조하십시오.USING(
절은 두 테이블에 존재해야하는 컬럼의 목록을 지정합니다. 테이블column_list
)a
와b
모두에 컬럼c1
,c2
및c3
가 포함되어있는 경우 다음의 결합은이 두 테이블의 컬럼들을 비교합니다.a LEFT JOIN b USING (c1, c2, c3)
두 테이블의
NATURAL [LEFT] JOIN
은 두 테이블에 존재하는 모든 컬럼을 지정하는USING
절을 포함INNER JOIN
또는LEFT JOIN
과 의미 적으로 동등하다로 정의됩니다.RIGHT JOIN
는LEFT JOIN
과 동일하게 작동합니다. 코드를 데이터베이스간에 이식 가능한 상태로 유지하기 위해RIGHT JOIN
대신LEFT JOIN
을 사용하는 것이 좋습니다.조인 구문의 설명에 표시된
{ OJ ... }
구문은 ODBC과의 호환성을 위해 존재합니다. 구문의 칼 한 괄호는 문자 그대로 기록해야합니다. 그들은 구문 설명의 다른 부분에서 이용되고있는 것 같은 메타 구문은 없습니다.SELECT left_tbl * FROM {OJ left_tbl LEFT OUTER JOIN right_tbl ON left_tbl.id = right_tbl.id} WHERE right_tbl.id IS NULL;
{ OJ ... }
내에서INNER JOIN
과RIGHT OUTER JOIN
등의 다른 형태의 결합을 사용할 수 있습니다. 이것은 일부 타사 응용 프로그램과의 호환성에 도움이 정식 ODBC 구문은 없습니다.STRAIGHT_JOIN
은 왼쪽 테이블이 항상 오른쪽 테이블 전에 읽을 것을 제외하면JOIN
과 동일합니다. 이것은 결합 최적화가 테이블을 잘못된 순서로 배치 (소수) 경우에 사용할 수 있습니다.
결합의 몇 가지 예 :
SELECT * FROM table1, table2; SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id; SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id; SELECT * FROM table1 LEFT JOIN table2 USING (id); SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id LEFT JOIN table3 ON table2.id = table3.id;
MySQL 5.0.12에서 조인 변경
자연 조인이나 USING
을 사용한 결합 (외부 조인의 변형을 포함)은 SQL : 2003 표준에 따라 처리됩니다. 그 목표는 NATURAL JOIN
과 JOIN ... USING
에 관련한 MySQL의 구문과 의미를 SQL : 2003에 맞추는 것이 었습니다. 그러나 결합 처리에서의 이러한 변화에 따라 일부 결합으로 서로 다른 출력 컬럼이 생성 될 가능성이 있습니다. 또한 이전 버전 (5.0.12 이전)에서는 제대로 작동하는 것 같았다 일부 쿼리를이 표준을 준수하도록 다시 작성해야합니다.
이러한 변화의 주요 측면으로 다음 5 가지가 있습니다.
MySQL이
NATURAL
이나USING
Join 연산의 결과 컬럼 (따라서FROM
절 전체의 결과)를 결정하는 방법.SELECT *
과SELECT
의 선택된 컬럼 목록에 전개.tbl_name
.*NATURAL
이나USING
결합 컬럼 이름 해결책.NATURAL
이나USING
결합의JOIN ... ON
로 변환.JOIN ... ON
의ON
조건 컬럼 이름 해결책.
다음 목록은 현재의 결합 처리의 일부 효과를 이전 버전에서 조인과 비교했을 때의 자세한 정보를 보여줍니다. "이전"이라는 용어는 "MySQL 5.0.12 이전"을 보여줍니다.
NATURAL
결합 또는USING
결합의 열이 이전과는 다를 수 있습니다. 구체적으로는 중복 출력 열이 표시되지 않게되어 있으며SELECT *
확장에서의 컬럼 순서가 이전과는 다를 수 있습니다.다음의 일련의 명령문을 생각해 보겠습니다.
CREATE TABLE t1 (i INT, j INT); CREATE TABLE t2 (k INT, j INT); INSERT INTO t1 VALUES (1,1); INSERT INTO t2 VALUES (1,1); SELECT * FROM t1 NATURAL JOIN t2; SELECT * FROM t1 JOIN t2 USING (j);
이전에는 이러한 문에서 다음 메시지가 생성되었습니다.
+------+------+------+------+ | i | j | k | j | +------+------+------+------+ | 1 | 1 | 1 | 1 | +------+------+------+------+ +------+------+------+------+ | i | j | k | j | +------+------+------+------+ | 1 | 1 | 1 | 1 | +------+------+------+------+
첫 번째
SELECT
문에서는 컬럼j
은 두 테이블에 나타나기 때문에 결합 컬럼입니다. 따라서 표준 SQL에 따라 출력은 2 회가 아닌 1 회만 표시되어야합니다. 마찬가지로, 두 번째 SELECT 문에서는 컬럼j
는USING
절에 지정되어 있기 때문에 출력은 2 회가 아닌 1 회만 표시되어야합니다. 그러나 두 경우 모두 중복 컬럼은 삭제되지 않습니다. 또한 표준 SQL에 따라 컬럼의 순서가 올바르지 않습니다.현재는이 명령문이 다음과 같이 출력됩니다.
+------+------+------+ | j | i | k | +------+------+------+ | 1 | 1 | 1 | +------+------+------+ +------+------+------+ | j | i | k | +------+------+------+ | 1 | 1 | 1 | +------+------+------+
중복 컬럼이 제거되고 컬럼 순서가 표준 SQL에 따라 올바르게되어 있습니다.
첫째, 결합 된 두 테이블의 합체 한 일반 컬럼이 첫 번째 테이블에 나타난 순서대로
둘째, 첫 번째 테이블에 고유 한 컬럼이 테이블에 나타난 순서대로
셋째, 두 번째 테이블에 고유 한 컬럼이 테이블에 나타난 순서대로
2 개의 일반 컬럼들을 대체 한 결과 컬럼은 COALESCE 연산을 사용하여 정의됩니다. 즉
t1.a
와t2.a
두 가지에 대해 결과 1 개의 결합 컬럼a
는a = COALESCE(t1.a, t2.a)
로 정의됩니다. 여기에서 :COALESCE (x, y) = (CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END)
이 병합 작업이 다른 몇개의 결합 인 경우, 그 결합의 결과 컬럼은 결합 된 테이블의 모든 컬럼의 연결로 구성됩니다. 이것은 이전과 동일합니다.
합체 한 컬럼의 정의의 결과로 외부 조인은 두 개의 열 중 하나가 항상
NULL
이면 합체 한 컬럼에NULL
이외의 컬럼의 값이 포함됩니다. 두 컬럼이NULL
이 아니거나 또는 두 컬럼이 값이면 모두 일반 컬럼에 같은 값이 포함되어 있기 때문에 합체 한 컬럼의 값으로 어느 쪽이 선택되는지는 문제가되지 않습니다. 이를 해석하기위한 간단한 방법으로 외부 조인 합체 한 컬럼이JOIN
의 내부 테이블의 일반 컬럼에 의해 표현된다고 생각합니다. 테이블t1(a,b)
와t2(a,c)
에 다음의 내용이 포함되어 있다고합니다.t1 t2 ---- ---- 1 x 2 z 2 y 3 w
이 때, 다음과 같이됩니다.
mysql>
SELECT * FROM t1 NATURAL LEFT JOIN t2;
+------+------+------+ | a | b | c | +------+------+------+ | 1 | x | NULL | | 2 | y | z | +------+------+------+여기에서는, 컬럼
a
에t1.a
값이 포함되어 있습니다.mysql>
SELECT * FROM t1 NATURAL RIGHT JOIN t2;
+------+------+------+ | a | c | b | +------+------+------+ | 2 | z | y | | 3 | w | NULL | +------+------+------+여기에서는, 컬럼
a
에t2.a
값이 포함되어 있습니다.이러한 결과를
JOIN ... ON
을 사용하여 그 이외에서는 동등한 쿼리와 비교하십시오.mysql>
SELECT * FROM t1 LEFT JOIN t2 ON (t1.a = t2.a);
+------+------+------+------+ | a | b | a | c | +------+------+------+------+ | 1 | x | NULL | NULL | | 2 | y | 2 | z | +------+------+------+------+mysql>
SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a = t2.a);
+------+------+------+------+ | a | b | a | c | +------+------+------+------+ | 2 | y | 2 | z | | NULL | NULL | 3 | w | +------+------+------+------+이전에는
USING
절을 다음 컬럼을 비교하는ON
절로 다시 작성할 수있었습니다. 예를 들어, 다음의 2 개의 어구는 의미 적으로 동일했다.a LEFT JOIN b USING (c1, c2, c3) a LEFT JOIN b ON a.c1 = b.c1 AND a.c2 = b.c2 AND a.c3 = b.c3
현재이 2 개의 어구는 완전히 동일 없게되어 있습니다.
어느 행이 결합 조건을 충족하는지의 판정에 관해서는 두 결합도 의미 적으로 동일하게 유지됩니다.
SELECT *
확장을 위해 어떤 컬럼을 표시할지의 판정에 관하여는이 두 가지의 결합은 의미 적으로 동일하지 않습니다.USING
결합이 대응하는 컬럼의 합체 한 값을 선택하는 반면ON
결합은 모든 테이블의 모든 컬럼을 선택합니다. 이전USING
결합의 경우SELECT *
는 다음의 값을 선택합니다.COALESCE (a.c1, b.c1) COALESCE (a.c2, b.c2) COALESCE (a.c3, b.c3)
ON
결합의 경우SELECT *
는 다음의 값을 선택합니다.a.c1, a.c2, a.c3, b.c1, b.c2, b.c3
내부 조인은
a.c1
과b.c1
의 두 컬럼에 같은 값이 포함되어 있기 때문에COALESCE(a.c1,b.c1)
는 두 컬럼 모두 동일합니다. 외부 조인 (LEFT JOIN
)에서는 두 개의 열 중 하나가NULL
이 될 수 있습니다. 그 컬럼은 결과에서 생략됩니다.
다중 natural 결합의 평가
NATURAL
이나USING
결합의 결과에 영향을주고, 심지어는 쿼리를 다시 작성해야 할 수도있는 매우 중요한 점에서 다릅니다. 3 개의 테이블t1(a,b)
,t2(c,b)
및t3(a,c)
가 각 테이블에t1(1,2)
,t2(10,2)
및t3(7,10)
의 1 행이 포함되어 있다고합니다. 또한 이러한 3 개의 테이블에 대해 다음NATURAL JOIN
을 실행합니다.SELECT ... FROM t1 NATURAL JOIN t2 NATURAL JOIN t3;
이전에는 두 번째 결합 왼쪽 피연산자가
t2
로 간주 된 반면, 현재는 중첩 된 결합(t1 NATURAL JOIN t2)
로 간주됩니다. 따라서t3
의 컬럼은t2
에서만 일반 컬럼에 체크되어 더욱t3
에t1
과 일반 컬럼이 포함되어있는 경우 이러한 열은 등가 결합 컬럼으로 사용되지 않습니다. 따라서 이전에는 이전 쿼리는 다음의 등가 결합으로 변환되었습니다.SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c;
그 결합은 또 다른 등가 조인 조건
(t1.a = t3.a)
가 없습니다. 그 결과, 본래 생성 할 빈 결과가 아닌 한 줄이 생성됩니다. 올바른 동등한 쿼리는 다음과 같습니다.SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c AND t1.a = t3.a;
현재 버전의 MySQL로 이전 버전과 동일한 쿼리 결과가 필요한 경우는 자연 조인을 첫번째 동등 결합으로 바꾼다.
이전 쉼표 연산자 (
,
)와JOIN
모두 동일한 우선 순위를 가지고 있었기 때문에, 결합 식t1, t2 JOIN t3
는((t1, t2) JOIN t3)
로 해석되었습니다. 현재는JOIN
의 우선 순위가 더 높기 때문에이 식은(t1, (t2 JOIN t3))
로 해석됩니다.ON
절은 결합 피연산자의 컬럼 만 참조 할 수 없으며 우선 순위의 변경에 따라 그 피연산자 설명에 대한 해석이 변경되기 때문에이 변경은 그 어구를 사용하는 명령문에 영향을 미칩니다.예 :
CREATE TABLE t1 (i1 INT, j1 INT); CREATE TABLE t2 (i2 INT, j2 INT); CREATE TABLE t3 (i3 INT, j3 INT); INSERT INTO t1 VALUES (1,1); INSERT INTO t2 VALUES (1,1); INSERT INTO t3 VALUES (1,1); SELECT * FROM t1, t2 JOIN t3 ON (t1.i1 = t3.i3);
이전에는이
SELECT
는(t1,t2)
로t1,t2
의 암시 적 그룹화를 위해 정당이었습니다. 현재는JOIN
이 우선되므로ON
절 피연산자는t2
와t3
됩니다.t1.i1
는 피연산자의 컬럼도 아니기 때문에 그 결과는「Unknown column 't1.i1' in 'on clause'」
라는 오류가 발생합니다. 이 결합의 처리를 가능하게하려면ON
절 피연산자(t1,t2)
와t3
가되도록 처음 두 개의 테이블을 명시 적으로 괄호로 그룹화합니다.SELECT * FROM (t1, t2) JOIN t3 ON (t1.i1 = t3.i3);
또는 쉼표 연산자의 사용을 피하고 대신
JOIN
을 사용합니다.SELECT * FROM t1 JOIN t2 JOIN t3 ON (t1.i1 = t3.i3);
이 변화는 또한 쉼표 연산자를
INNER JOIN
,CROSS JOIN
,LEFT JOIN
및RIGHT JOIN
(이들은 모두 현재 쉼표 연산자보다 높은 우선 순위를 가지고 있습니다)와 혼합시키고있는 문에도 적용됩니다 .이전에는
ON
절은 그 오른쪽에 지정되어있는 테이블의 컬럼을 참조 할 수있었습니다. 현재는ON
절은 자신의 피연산자 밖에 볼 수 없습니다.예 :
CREATE TABLE t1 (i1 INT); CREATE TABLE t2 (i2 INT); CREATE TABLE t3 (i3 INT); SELECT * FROM t1 JOIN t2 ON (i1 = i3) JOIN t3;
i3은 ON 절의 피연산자가 아닌 t3의 열이기 때문에 명령문은 Unknown column 'i3' in 'on clause' 오류로 실패합니다. 조인을 처리하려면 다음과 같이 명령문을 다시 작성하십시오.
SELECT * FROM t1 JOIN t2 JOIN t3 ON (i1 = i3);
NATURAL
이나USING
결합 컬럼 이름의 해결이 이전과는 다릅니다.FROM
절의 외부에있는 컬럼 이름의 경우 MySQL은 현재 이전과 비교하여 쿼리의 슈퍼 세트를 처리합니다. 즉, MySQL이 이전 일부 컬럼이 모호하다는 오류를 발행 한 경우에도 그 쿼리는 현재 올바르게 처리됩니다. 이것은 MySQL이 현재NATURAL
이나USING
결합 일반 컬럼을 단일 컬럼으로 처리하는 쿼리가 이러한 열을 참조하더라도 쿼리 컴파일러가 그 컬럼을 모호하다고 간주 않음에 따라 .예 :
SELECT * FROM t1 NATURAL JOIN t2 WHERE b> 1;
이전이 쿼리에서 오류
ERROR 1052 (23000): Column 'b' in where clause is ambiguous
이 생성되었습니다. 현재는이 쿼리에서 올바른 결과가 생성됩니다.+------+------+------+ | b | c | y | +------+------+------+ | 4 | 2 | 3 | +------+------+------+
SQL : 2003 표준과 비교했을 때 MySQL의 1 개의 확장으로서 MySQL에서는
NATURAL
이나USING
결합의 공통 (합체 한) 열 (이전과) 자격있는 반면 표준에서는 그것이 금지 하는 점이 있습니다.