답변:
SQL JOIN
?SQL JOIN
두 개 이상의 데이터베이스 테이블에서 데이터를 검색하는 방법입니다.
SQL JOIN
?총 5 개가 JOIN
있습니다. 그들은 :
1. JOIN or INNER JOIN
2. OUTER JOIN
2.1 LEFT OUTER JOIN or LEFT JOIN
2.2 RIGHT OUTER JOIN or RIGHT JOIN
2.3 FULL OUTER JOIN or FULL JOIN
3. NATURAL JOIN
4. CROSS JOIN
5. SELF JOIN
이러한 종류의 JOIN
에서 두 테이블의 조건과 일치하는 모든 레코드를 가져 오며 일치하지 않는 두 테이블의 레코드는보고되지 않습니다.
다시 말해, 다음 두 가지 INNER JOIN
사실에 기초합니다. 두 테이블에서 일치하는 항목 만 나열되어야합니다.
• 그래도 참고 JOIN
다른없는 JOIN
키워드 (같은 INNER
, OUTER
, LEFT
, 등)가있다 INNER JOIN
. 다시 말해, 다음 JOIN
에 대한 구문 설탕입니다 INNER JOIN
( JOIN과 INNER JOIN의 차이점 참조 ).
OUTER JOIN
검색
한 테이블에서 일치하는 행과 다른 테이블의 모든 행 또는 모든 테이블의 모든 행 (일치가 있는지 여부는 중요하지 않음)입니다.
외부 조인에는 세 가지 종류가 있습니다.
2.1 왼쪽 외부 조인 또는 왼쪽 조인
이 조인은 오른쪽 테이블의 일치하는 행과 함께 왼쪽 테이블의 모든 행을 반환합니다. 오른쪽 테이블에 일치하는 열이 없으면 NULL
값 을 반환 합니다.
2.2 오른쪽 외부 조인 또는 오른쪽 조인
이 JOIN
모든 반환 왼쪽 테이블에서 일치하는 행과 함께 오른쪽 테이블에서 행. 왼쪽 테이블에 일치하는 열이 없으면 NULL
값 을 반환 합니다.
2.3 전체 외부 가입 또는 전체 가입
이 JOIN
콤바인 LEFT OUTER JOIN
과 RIGHT OUTER JOIN
. 조건이 충족되면 두 테이블에서 행을 반환하고 NULL
일치하지 않으면 값을 반환 합니다.
다시 말해, OUTER JOIN
다음 중 하나에 해당합니다. 테이블 중 하나 (오른쪽 또는 왼쪽) 또는 테이블 (FULL) 중 일치하는 항목 만 나열해야합니다.
Note that `OUTER JOIN` is a loosened form of `INNER JOIN`.
두 가지 조건을 기반으로합니다.
JOIN
평등에 대한 동일한 이름을 가진 모든 컬럼에 이루어집니다.이것은 본질적으로 더 이론적 인 것으로 보이며 결과적으로 대부분의 DBMS는 이것을 지원하지 않아도됩니다.
관련된 두 테이블의 카티 전 곱입니다. 의 결과는 CROSS JOIN
대부분의 상황에서 의미가 없습니다. 또한, 우리는 이것을 전혀 필요로하지 않을 것입니다 (또는 최소한 정확해야합니다).
그것은 다른 양식을하지 않습니다 JOIN
오히려 그것이이다, JOIN
( INNER
, OUTER
자체 테이블 등).
JOIN
절에 사용 된 연산자에 따라 두 가지 유형이있을 수 있습니다 JOIN
. 그들은
모든 JOIN
유형 ( INNER
, OUTER
등)에 대해 등호 연산자 (=) 만 사용하는 경우, JOIN
는입니다 EQUI JOIN
.
이것은 동일 EQUI JOIN
하지만>, <,> = 등과 같은 다른 모든 연산자를 허용합니다.
많은 사람들이 모두 고려
EQUI JOIN
하고 세타가JOIN
유사INNER
,OUTER
등JOIN
의. 그러나 나는 그것이 실수라고 생각하고 아이디어를 모호하게 만듭니다. 때문에INNER JOIN
,OUTER JOIN
등 모든 테이블 및 반면 데이터와 연결EQUI JOIN
하고THETA JOIN
단지 우리가 이전에 사용하는 사업자와 연결되어 있습니다.다시 말하지만,
NATURAL JOIN
어떤 종류의 "특별한" 것으로 간주하는 사람들이 많이EQUI JOIN
있습니다. 사실, 내가 언급 한 첫 번째 조건 때문에 사실입니다NATURAL JOIN
. 그러나 우리는 이것을 단순히NATURAL JOIN
혼자 로 제한 할 필요는 없습니다 .INNER JOIN
sOUTER JOIN
등도EQUI JOIN
너무 될 수 있습니다 .
정의:
JOINS는 여러 테이블에서 동시에 결합 된 데이터를 쿼리하는 방법입니다.
RDBMS와 관련하여 5 가지 유형의 조인이 있습니다.
동등 조인 : 동일 조건에 따라 두 테이블의 공통 레코드를 결합합니다. 기술적으로, 항등 연산자 (=)를 사용하여 한 테이블의 기본 키 값과 다른 테이블의 외래 키 값을 비교하여 조인하므로 결과 집합에는 두 테이블의 공통 (일치 된) 레코드가 포함됩니다. 구현에 대해서는 INNER-JOIN을 참조하십시오.
자연 결합 : SELECT 조작이 중복 열을 생략하는 Equi-Join의 개선 된 버전입니다. 구현에 대해서는 INNER-JOIN을 참조하십시오.
동일하지 않은 조인 : 조인 조건이 동일한 연산자 (=) 이외의 다른 연산자를 사용하는 경우 동일 조인의 반대입니다 (예 :! =, <=,> =,>, <또는 BETWEEN 등). 구현에 대해서는 INNER-JOIN을 참조하십시오.
자체 결합 : : 테이블이 자체 결합 된 사용자 정의 결합 동작. 이는 일반적으로 자체 참조 테이블 (또는 단항 관계 엔터티)을 쿼리하는 데 필요합니다. 구현에 대해서는 INNER-JOIN을 참조하십시오.
직교 곱 : 조건없이 두 테이블의 모든 레코드를 교차 결합합니다. 기술적으로 WHERE-Clause가없는 쿼리 결과 집합을 반환합니다.
SQL 문제와 발전에 따라 3 가지 유형의 조인이 있으며 이러한 유형의 조인을 사용하여 모든 RDBMS 조인을 수행 할 수 있습니다.
INNER-JOIN : 두 테이블에서 일치하는 행을 병합 (또는 결합)합니다. 일치는 테이블의 공통 열과 비교 작업을 기반으로 수행됩니다. 평등 기반 조건 인 경우 : EQUI-JOIN 수행, 그렇지 않으면 Non-EQUI-Join
OUTER-JOIN : 두 테이블에서 일치하는 행과 일치하지 않는 행을 NULL 값으로 병합 (또는 결합)합니다. 그러나 하위 유형 (LEFT OUTER JOIN 및 RIGHT OUTER JOIN)으로 첫 번째 테이블 또는 두 번째 테이블에서 일치하지 않는 행을 선택하는 것과 같이 일치하지 않는 행의 선택을 사용자 정의 할 수 있습니다.
2.1. LEFT Outer JOIN (일명 LEFT-JOIN) : 두 테이블에서 일치하는 행을 리턴하고 LEFT 테이블 (즉, 첫 번째 테이블)에서만 일치하지 않는 행을 리턴합니다.
2.2. RIGHT 외부 조인 (일명 RIGHT-JOIN) : 두 테이블에서 일치하는 행을 반환하고 RIGHT 테이블에서만 일치하지 않는 행을 반환합니다.
2.3. FULL OUTER JOIN (일명 OUTER JOIN) : 두 테이블에서 일치하고 일치하지 않는 결과를 반환합니다.
CROSS-JOIN : 이 조인은 Cartesian 제품을 수행하는 대신 병합 / 결합하지 않습니다.
참고 : 자체 JOIN은 요구 사항에 따라 INNER-JOIN, OUTER-JOIN 및 CROSS-JOIN을 통해 달성 할 수 있지만 테이블은 자체적으로 조인해야합니다.
1.1 : INNER-JOIN : 동일 조인 구현
SELECT *
FROM Table1 A
INNER JOIN Table2 B ON A.<Primary-Key> =B.<Foreign-Key>;
1.2 : INNER-JOIN : Natural-JOIN 구현
Select A.*, B.Col1, B.Col2 --But no B.ForeignKeyColumn in Select
FROM Table1 A
INNER JOIN Table2 B On A.Pk = B.Fk;
1.3 : 비 동등 조인 구현의 INNER-JOIN
Select *
FROM Table1 A INNER JOIN Table2 B On A.Pk <= B.Fk;
1.4 : SELF-JOIN을 사용한 INNER-JOIN
Select *
FROM Table1 A1 INNER JOIN Table1 A2 On A1.Pk = A2.Fk;
2.1 : OUTER JOIN (전체 외부 조인)
Select *
FROM Table1 A FULL OUTER JOIN Table2 B On A.Pk = B.Fk;
2.2 : 왼쪽 가입
Select *
FROM Table1 A LEFT OUTER JOIN Table2 B On A.Pk = B.Fk;
2.3 : 오른쪽 가입
Select *
FROM Table1 A RIGHT OUTER JOIN Table2 B On A.Pk = B.Fk;
3.1 : 크로스 조인
Select *
FROM TableA CROSS JOIN TableB;
3.2 : 크로스 조인-셀프 조인
Select *
FROM Table1 A1 CROSS JOIN Table1 A2;
//또는//
Select *
FROM Table1 A1,Table1 A2;
intersect
/ except
/ union
; 여기서 원은 번호가 매겨진 레이블과 같이 left
& 로 반환되는 행 right
join
입니다. AXB 사진은 말도 안됩니다. cross join
= inner join on 1=1
&는 첫 번째 다이어그램의 특별한 경우입니다.
UNION JOIN
있습니다. 이제 SQL : 2003에서 더 이상 사용되지 않습니다.
흥미롭게도 대부분의 다른 답변에는 다음 두 가지 문제가 있습니다.
나는 최근에 주제에 대한 기사를 작성했습니다 : SQL 에서 테이블에 참여하는 여러 가지 방법에 대한 아마도 불완전하고 포괄적 인 안내서 . 여기에서 요약합니다.
JOIN 이 두 개의 조인 된 테이블 사이에 데카르트 곱을 작성하기 때문에 벤 다이어그램이이를 부정확하게 설명하는 이유 입니다. Wikipedia는이를 잘 보여줍니다.
직교 곱의 SQL 구문은 CROSS JOIN
입니다. 예를 들면 다음과 같습니다.
SELECT *
-- This just generates all the days in January 2017
FROM generate_series(
'2017-01-01'::TIMESTAMP,
'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day'
) AS days(day)
-- Here, we're combining all days with all departments
CROSS JOIN departments
어느 테이블의 모든 행을 다른 테이블의 모든 행과 결합합니다.
출처:
+--------+ +------------+
| day | | department |
+--------+ +------------+
| Jan 01 | | Dept 1 |
| Jan 02 | | Dept 2 |
| ... | | Dept 3 |
| Jan 30 | +------------+
| Jan 31 |
+--------+
결과:
+--------+------------+
| day | department |
+--------+------------+
| Jan 01 | Dept 1 |
| Jan 01 | Dept 2 |
| Jan 01 | Dept 3 |
| Jan 02 | Dept 1 |
| Jan 02 | Dept 2 |
| Jan 02 | Dept 3 |
| ... | ... |
| Jan 31 | Dept 1 |
| Jan 31 | Dept 2 |
| Jan 31 | Dept 3 |
+--------+------------+
쉼표로 구분 된 테이블 목록을 작성하면 다음과 같이됩니다.
-- CROSS JOINing two tables:
SELECT * FROM table1, table2
이 INNER JOIN
단지는 여과 CROSS JOIN
필터 선언문이 호출되는 경우 Theta
관계 대수에서.
예를 들어 :
SELECT *
-- Same as before
FROM generate_series(
'2017-01-01'::TIMESTAMP,
'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day'
) AS days(day)
-- Now, exclude all days/departments combinations for
-- days before the department was created
JOIN departments AS d ON day >= d.created_at
키워드 INNER
는 선택 사항입니다 (MS Access 제외).
Theta-JOIN의 특별한 종류는 우리가 가장 많이 사용하는 equi JOIN입니다. 술어는 한 테이블의 기본 키를 다른 테이블의 외래 키와 결합합니다. 설명을 위해 Sakila 데이터베이스 를 사용하면 다음 과 같이 쓸 수 있습니다.
SELECT *
FROM actor AS a
JOIN film_actor AS fa ON a.actor_id = fa.actor_id
JOIN film AS f ON f.film_id = fa.film_id
이것은 모든 배우를 영화와 결합합니다.
또는 일부 데이터베이스에서 :
SELECT *
FROM actor
JOIN film_actor USING (actor_id)
JOIN film USING (film_id)
USING()
구문은 동작의 테이블을 가입하고 그 두 열에 동등 술어를 작성 양쪽 있어야 열을 지정 가능하다.
다른 답변에서는이 "JOIN 유형"을 별도로 나열했지만 의미가 없습니다. Theta-JOIN 또는 INNER JOIN의 특수한 경우 인 equi JOIN의 구문 설탕 양식 일뿐입니다. NATURAL JOIN은 단순히 결합되는 두 테이블에 공통 인 모든 컬럼을 수집 하고USING()
해당 컬럼을 결합합니다 . 실수로 일치하기 때문에 ( Sakila 데이터베이스의LAST_UPDATE
열과 같은) 거의 유용하지 않습니다 .
구문은 다음과 같습니다.
SELECT *
FROM actor
NATURAL JOIN film_actor
NATURAL JOIN film
이제는 몇 가지 직교 곱을 만드는 OUTER JOIN
것과는 조금 다릅니다 . 우리는 쓸 수있다:INNER JOIN
UNION
-- Convenient syntax:
SELECT *
FROM a LEFT JOIN b ON <predicate>
-- Cumbersome, equivalent syntax:
SELECT a.*, b.*
FROM a JOIN b ON <predicate>
UNION ALL
SELECT a.*, NULL, NULL, ..., NULL
FROM a
WHERE NOT EXISTS (
SELECT * FROM b WHERE <predicate>
)
아무도 후자를 쓰지 않기를 원하므로 OUTER JOIN
데이터베이스에 최적화되어 있습니다.
마찬가지로 INNER
키워드 OUTER
는 선택 사항입니다.
OUTER JOIN
세 가지 맛이 있습니다.
LEFT [ OUTER ] JOIN
: JOIN
표현식 의 왼쪽 테이블이 위와 같이 공용체에 추가됩니다.RIGHT [ OUTER ] JOIN
: JOIN
표현식 의 오른쪽 테이블이 위와 같이 공용체에 추가됩니다.FULL [ OUTER ] JOIN
: JOIN
표현식 의 두 테이블이 위에 표시된대로 공용체에 추가됩니다.이 모든 키워드 USING()
또는 키워드와 결합 할 수 있습니다 NATURAL
( 실제로는 NATURAL FULL JOIN
최근에 실제 사용 사례를 가졌습니다 )
Oracle과 SQL Server에는 역사적으로 사용되지 않는 몇 가지 OUTER JOIN
구문이 있습니다.이 구문은 SQL 표준이 이에 대한 구문을 갖기 전에 이미 지원 되었습니다.
-- Oracle
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id = fa.actor_id(+)
AND fa.film_id = f.film_id(+)
-- SQL Server
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id *= fa.actor_id
AND fa.film_id *= f.film_id
그렇게 말했지만이 구문을 사용하지 마십시오. 오래된 블로그 게시물 / 레거시 코드에서 인식 할 수 있도록 여기에 나열하십시오.
OUTER JOIN
이를 아는 사람은 거의 없지만 SQL 표준은 파티션을 지정 OUTER JOIN
하고 Oracle 은이를 구현합니다. 다음과 같이 쓸 수 있습니다.
WITH
-- Using CONNECT BY to generate all dates in January
days(day) AS (
SELECT DATE '2017-01-01' + LEVEL - 1
FROM dual
CONNECT BY LEVEL <= 31
),
-- Our departments
departments(department, created_at) AS (
SELECT 'Dept 1', DATE '2017-01-10' FROM dual UNION ALL
SELECT 'Dept 2', DATE '2017-01-11' FROM dual UNION ALL
SELECT 'Dept 3', DATE '2017-01-12' FROM dual UNION ALL
SELECT 'Dept 4', DATE '2017-04-01' FROM dual UNION ALL
SELECT 'Dept 5', DATE '2017-04-02' FROM dual
)
SELECT *
FROM days
LEFT JOIN departments
PARTITION BY (department) -- This is where the magic happens
ON day >= created_at
결과의 일부 :
+--------+------------+------------+
| day | department | created_at |
+--------+------------+------------+
| Jan 01 | Dept 1 | | -- Didn't match, but still get row
| Jan 02 | Dept 1 | | -- Didn't match, but still get row
| ... | Dept 1 | | -- Didn't match, but still get row
| Jan 09 | Dept 1 | | -- Didn't match, but still get row
| Jan 10 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 11 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 12 | Dept 1 | Jan 10 | -- Matches, so get join result
| ... | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 31 | Dept 1 | Jan 10 | -- Matches, so get join result
여기서 요점은 조인의 분할 된쪽에있는 모든 행 JOIN
이 "JoIN의 다른 쪽"에있는 것과 일치 하는지 여부에 관계없이 결과에 적용된다는 것입니다. 간단히 말해 : 보고서에서 희소 데이터를 채우는 것입니다. 굉장히 유용하다!
진심이야? 다른 답변이 없습니까? 물론 , 불행히도 (아래의 ANTI JOIN과 마찬가지로) SQL에는 네이티브 구문이 없기 때문에 아닙니다 . 그러나 우리는 사용할 수 있습니다 IN()
와 EXISTS()
영화에서 연주 한 모든 배우를 찾기 위해, 예를 :
SELECT *
FROM actor a
WHERE EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
WHERE a.actor_id = fa.actor_id
반이 술어 가입으로 술어는 역할을합니다. 믿지 않으면 Oracle과 같은 실행 계획을 확인하십시오. 데이터베이스가 EXISTS()
술어가 아닌 SEMI JOIN 조작을 실행 함을 알 수 있습니다.
이 SEMI의 정반대입니다 가입 ( 사용하지 않도록주의해야 NOT IN
하지만 , 그것은 중요한주의를 가지고로)
영화가없는 배우는 다음과 같습니다.
SELECT *
FROM actor a
WHERE NOT EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
일부 사람들 (특히 MySQL 사용자)도 다음과 같이 ANTI JOIN을 작성합니다.
SELECT *
FROM actor a
LEFT JOIN film_actor fa
USING (actor_id)
WHERE film_id IS NULL
역사적인 이유는 성능이라고 생각합니다.
세상에, 이건 너무 멋지다. 나는 그것을 언급하는 유일한 사람입니까? 다음은 멋진 검색어입니다.
SELECT a.first_name, a.last_name, f.*
FROM actor AS a
LEFT OUTER JOIN LATERAL (
SELECT f.title, SUM(amount) AS revenue
FROM film AS f
JOIN film_actor AS fa USING (film_id)
JOIN inventory AS i USING (film_id)
JOIN rental AS r USING (inventory_id)
JOIN payment AS p USING (rental_id)
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
GROUP BY f.film_id
ORDER BY revenue DESC
LIMIT 5
) AS f
ON true
배우 당 최고 5 개의 수입 영화를 찾을 수 있습니다. TOP-N-perthing 쿼리가 필요할 때마다 LATERAL JOIN
친구가됩니다. SQL Server 사용자 인 JOIN
경우 이름 아래 에서이 유형 을 알고 있습니다APPLY
SELECT a.first_name, a.last_name, f.*
FROM actor AS a
OUTER APPLY (
SELECT f.title, SUM(amount) AS revenue
FROM film AS f
JOIN film_actor AS fa ON f.film_id = fa.film_id
JOIN inventory AS i ON f.film_id = i.film_id
JOIN rental AS r ON i.inventory_id = r.inventory_id
JOIN payment AS p ON r.rental_id = p.rental_id
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
GROUP BY f.film_id
ORDER BY revenue DESC
LIMIT 5
) AS f
LATERAL JOIN
또는 APPLY
표현식이 실제로 여러 행을 생성하는 "상관 된 하위 쿼리" 이므로 부정 행위 일 수 있습니다. 그러나 "상관 된 하위 쿼리"를 허용하면 다음에 대해서도 이야기 할 수 있습니다.
이것은 실제로 Oracle과 Informix에 의해서만 구현되지만 배열 및 / 또는 XML을 사용하는 PostgreSQL 및 XML을 사용하는 SQL Server에서 에뮬레이션 할 수 있습니다.
MULTISET
상관 된 하위 쿼리를 생성하고 결과 행 집합을 외부 쿼리에 중첩시킵니다. 아래 쿼리는 모든 액터를 선택하고 각 액터마다 중첩 된 컬렉션으로 영화를 수집합니다.
SELECT a.*, MULTISET (
SELECT f.*
FROM film AS f
JOIN film_actor AS fa USING (film_id)
WHERE a.actor_id = fa.actor_id
) AS films
FROM actor
당신이 보았 듯이,이 단지 "지루한"보다 가입의 많은 종류가 있습니다 INNER
, OUTER
그리고 CROSS JOIN
그 일반적으로 언급된다. 내 기사에 자세한 내용이 있습니다. 그리고 Venn 다이어그램 사용을 그만 설명하십시오.