database.sarang.net
UserID
Passwd
Database
ㆍDBMS
MySQL
PostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
DBMS Tutorials 861 게시물 읽기
 News | Q&A | Columns | Tutorials | Devel | Files | Links
No. 861
SQL 에서 Join 이란...
작성자
정재익(advance)
작성일
2003-10-22 22:23
조회수
18,515

[ SQL 에서 join 이란... ]

 

출처 : phpschool , 글쓴이 : 명랑폐인™

 

이 컬럼에서 데이터베이스 테이블 디자인에 대해 얘기하기 전에, 필자는 SQL SELECT 문에 대해 설명했었다. 이 문장은 다음과 같은 일반적인 형식을 갖고 있었다:

SELECT column_name(s) [AS alias] FROM table_name [ORDER BY column_name(s) (ASC | DESC) ] WHERE (search_criteria);

CD의 데이터베이스를 검색할 때 가장 다양하게 사용했던 형식이다. 그러나 필자는 하나의 데이터베이스 테이블에서 레코드를 가져오는 것만 살펴보았다. 지금까지 테이블 관계에 대해 설명했기 때문에, 일련의 관계형 데이터베이스 테이블에서 레코드를 가져오기 위해 SELECT문을 사용하는 방법에 대해 알아볼 것이다.

Peter Gabriel의 CD에 관한 데이터베이스 레코드를 보자. 다음 두 테이블은 아티스트와 CD 정보를 포함하고, 강조되어 있는 ArtistID 필드에 일대다 연결(하나의 아티스트에 여러 개의 CD에 연결되는)을 갖고 있다.

ArtistID ArtistName
22 Peter Gabriel


CDID ArtistID Title Year Quality
15 22 So 1984 10
16 22 Us 1992 10


다음 SQL 문장을 사용하여 Peter Gabriel에 대한 모든 아티스트 정보를 찾을 수 있다.

SELECT * FROM Artists WHERE ArtistID=22;

그리고 다음 SQL 문장을 사용하여 CD의 모든 정보를 찾을 수 있다.

SELECT * FROM CDs WHERE ArtistID=22;

이것은 여러분에게 음악가와 음악가의 앨범에 대한 두 종류의 데이터를 제공한다.

위와 같은 모든 정보를 하나로 가져올 수 있다면 좋지 않을까?

사실, 필자는 효율성을 높이기 위해 이 모든 정보를 두 개의 테이블로 나누었다.

관계형 테이블이 가지는 주요한 요점은 두 개의 테이블을 가져올 수 있고, 다음 테이블과 같이 아티스트와 CD 정보로 구성된 아주 큰 하나의 테이블로 합칠 수 있다는 것이다.

ArtistID Title Year Quality
Peter Gabriel So 1984 10
Peter Gabriel Us 1992 10


두 테이블을 하나도 조인(join)하거나 연결하기 위해 공통된 키 필드(여기서는 ArtistID 필드)가 필요하다. 위에 있는 두 SQL 문장을 가져와서, 각각의 테이블에서 가져온 모든 정보로 구성된 하나의 가상 테이블을 만들기 위해 두 테이블을 함께 썼다.

SELECT * FROM Artist,CD WHERE (CD.ArtistID=Artist.ArtistID);

이것은 다음과 같이 보일 것이다.

CDID ArtistID Artist Title Year Quality



Peter Gabriel에 대한 ArtistID로 SQL 문을 제한한다면 다음과 같이 질의를 작성한다.

SELECT * FROM Artist,CD WHERE (CD.ArtistID=Artist.ArtistID) AND Artist.ArtistID=22;

결과는 다음과 같다.

CDID ArtistID Artist Title Year Quality
15 22 Peter Gabriel So 1984 10
16 22 Peter Gabriel Us 1992 10


SQL SELECT문에 WHERE 절에 등호(=) 연산자를 사용하여 공통(키) 필드로 두 테이블을 연결할 수 있다.


JOIN 키워드 사용하기
테이블을 JOIN 하기 위해 등호(=) 연산자를 사용할 뿐만 아니라, SQL은 두 개 이상의 테이블 사이에 보다 복잡한 JOIN에 사용되는 연산자를 포함하고 있다. SQL 문은 다음과 같다.

SELECT * FROM Artist,CD WHERE (CD.ArtistID=Artist.ArtistID) AND Artist.ArtistID=22;

명시적으로 JOIN된 테이블을 만들기 위해 다음과 같이 할 수 있다.

SELECT * FROM (Artist INNER JOIN CD ON CD.ArtistID=Artist.ArtistID) WHERE Artist.ArtistID=22;

두 개의 같은 문장에서 알 수 있는 것처럼, 두 번째 질의는 두 개의 관계형 테이블을 JOIN 하여 가상 테이블을 만드는 것을 더욱 명확하게 해준다. 그리고 나서 올바른 ArtistID로 결과 테이블을 필터링한다. 지금까지, 우리는 JOIN 대신에 INNER JOIN을 사용해야 하는지에 대해 무시했다. - 그것은 그 자체만으로도 가치 있는 주제이다.

두 개의 같은 문장에서 알 수 있는 것처럼, 두 번째 질의는 두 관계형 테이블을 하나로 JOIN하여 하나의 가상 테이블을 만들고 나서 올바른 ArtistID로 결과 테이블을 필터링한다는 점에서 더 명확하다. 지금까지 단순히 JOIN 대신에 INNER JOIN을 사용해야 하는지에 대해서는 설명하지 않았다.


SELF JOIN은 무엇인가?
SELF-JOIN은 특정 유형의 상황 특히, 더 이상 두 개의 테이블로 나누는 것과 같은 정규화가 필요 없는 데이터베이스 테이블을 갖고 있는 경우- 에만 유용한 도구중의 하나다. 전형적인 경우는 데이터를 갖고 있는 한 테이블이 동일한 테이블에 저장된 데이터 값에 대한 링크를 포함하고 있는 경우다.

SQL 책에서 보게되는 표준이나 다름없는 예제는 Employees 테이블의 레코드에 링크를 갖고 있는-Manager ID 필드를 포함하고 있는- 다음과 같은 Employee 테이블이다.

Employees
EmployeeID EmployeeName ManagerID
61 Sue Smith (null)
62 David Jones 61
63 Troy Parker 61
64 Claire Smith-Jones 63
65 Grover Rivers 63

각 종업원의 관리자 이름을 반환하는 질의는 어떻게 만드는가? 한 가지는 루프 안에 중첩 질의를 넣는 것이다. 이것은 PHP, ASP, ColdFusion, JSP와 같은 웹 개발자들이 이러한 문제를 만나게 되면 사용하는 가장 일반적인 접근 방법이다. 물론, 이러한 접근 방법은 수행 성능 측면에서 끔찍한 해결방법이다. SQL JOIN을 이용하는 것이 서버 사이드 기술을 사용하여 각각의 질의를 조합하는 것보다 훨씬 더 빠르다. 여기서는 서버 사이드 기술 대신에 SELF JOIN을 사용할 것이다.




SELF JOIN 사용하기
SELF JOIN은 하나의 테이블이 스스로를 JOIN하는 일반 SQL JOIN이다. SQL JOIN은 테이블의 각 인스턴스에 개별적인 이름을 부여하는 테이블 이름 별칭(alias)을 사용하여 수행된다. 예를 들면 다음과 같다:

SELECT E1.EmployeeName AS Employee, E2.EmployeeName AS Manager FROM Employees AS E1 INNER JOIN Employees AS E2 ON E1.ManagerID = E2.EmployeeID

위와 같은 SQL 코드는 다음과 같은 두 개의 동일한 테이블을 효율적으로 생성한다.

Ei(Employees)
EmployeeID EmployeeName ManagerID
61 Sue Smith (null)
62 David Jones 61
63 Troy Parker 61
64 Claire Smith-Jones 63
65 Grover Rivers 63

E2(Employees)
EmployeeID EmployeeName ManagerID
61 Sue Smith (null)
62 David Jones 61
63 Troy Parker 61
64 Claire Smith-Jones 63
65 Grover Rivers 63

이 테이블에서는 강조된 컬럼이 JOIN되었다. 실제로 테이블에 대한 다른 복사본을 만든 것이 아니라는 것에 주목한다. 테이블 그자체를 JOIN했지만, 테이블을 두 개의 테이블로 생각한다면 이것은 더 이해하기 쉽다.(적어도 필자는 그렇다!)




SQL OUTER JOIN
모든 종류의 SQL JOIN은 효율적으로 하나의 테이블에 있는 열과 JOIN 하는 다른 테이블에 있는 열을 곱한다.(그리고 많은 테이블이 JOIN 연산에 참여하는 것처럼 테이블을 포함하기 위해 확장될 수 있다.

카테시안 곱(CROSS JOIN)에 대해서 얘기할 때, 한 테이블의 모든 행과 다른 테이블의 모든 행을 곱한 결과로 만들어지는 열을 볼 수 있었다. INNER JOIN은 같은 값을 갖고 있는 키 필드를 갖고 있는 행만을 가져오기 위해 이러한 카테시안 곱으로 만들어지는 행에 대한 유용한 필터를 제공한다. INNER JOIN 연산의 결과는 JOIN한 두 테이블에 있는 각 키를 하나의 행에 갖고 있는 행이 된다. 그러나 한 테이블에 있는 행에 있는 키 값과 다른 테이블에 있는 키 값이 일치하지 않는 경우에는 어떤가? INNER JOIN은 그러한 행을 무시한다.

OUTER JOIN은 INNER JOIN에서 빠지는 행을 포함하기 위해 사용한다. 예제로 사용했던 CD 데이터베이스를 사용하면 보다 명확하게 이해가 될 것이다. 지금까지, CD 컬렉션의 카탈로그를 만들기 위해 아티스트(Artist) 데이터와 CD 데이터를 가져오는 데 JOIN을 사용했다. 그러나 필자가 라디오에서 새로운 아티스트에 관해 얘기하는 것을 들었고, 즉시 그 아티스트 여기서는 David Gray -를 데이터베이스에 추가하기로 한다고 하자.

Artists
ArtistID ArtistName

1 Peter Gabriel
2 Bruce Hornsby
3 Lyle Lovett
4 Beach Boys
5 David Gray

Artists와 CD 테이블을 가지고 INNER JOIN을 사용했다면, 결과는 다음과 같을 것이다.

SELECT * FROM Artists, CDs WHERE Artists.ArtistID=CDs.ArtistID

CDID CDs.ArtistID Artists.ArtistID ArtisName Title Year
1 1 1 Peter Gabriel So 1984
2 1 1 Peter Gabriel Us 1992
3 2 2 Bruce Hornsby The Way It Is 1986
4 2 2 Bruce Hornsby Scenes from the Southside 1990
5 1 1 Peter Gabriel Security 1990
6 3 3 Lyle Lovett Joshua Judges Ruth 1992
7 4 4 Beach Boys Pet Sounds 1966

이 결과는 정확하게 필자의 카탈로그를 보여준다. 그러나 필자가 카탈로그에 추가할 예정인 다른 아티스트와 David Gray는 어떤가? CDs.ArtistID=5인 일치하는 행이 없기 때문에 그러한 아티스트들은 이 결과에서 빠져있다. 여러분은 중요한게 아니라고 말할지도 모르지만, 만약 두 테이블이 Customer와 Orders라면? 또는 Orders와 Items라면 어떤가?

첫번째 경우에 주문을 한 고객만이 리포트에 나타날 것이다. 두번째 경우에는 실제로 주문을 받은 항목만이 나타나게 될 것이다. 이러한 종류의 빠진 정보들은 어떤 종류의 계산을 완전히 망칠것이다! OUTER JOIN 연산은 이러한 문제를 수정할 수 있다.




OUTER JOIN 사용하기
OUTER JOIN은 다음과 같은 세가지가 있다.


LEFT OUTER JOIN (*=)

RIGHT OUTER JOIN (=*)

FULL OUTER JOIN

OUTER JOIN의 목적은 빠진 행이나 일치하지 않는 행을 포함하기 위한 것이라는 것이다. 여러분은 이 세가지 OUTER JOIN이 무엇을 의미하는지 아마도 이해할 수 있을 것이다. LEFT, RIGHT, FULL 구문은 모두 어느 것이 테이블의 일치하지 않는 컬럼을 포함하는 것인지를 지정하는 것이다. CD 컬렉션 예제를 수정하기를 원한다면, 우리는 INNER JOIN을 다음과 같은 OUTER JOIN으로 바꿀 수 있다.

SELECT * FROM Artists, CDs WHERE Artists.ArtistID *= CDs.ArtistID

LEFT OUTER JOIN 연산자는 JOIN 되는 테이블의 왼쪽 편에 있는 모든 열, 여기서는 Artists 테이블에 있는 열을 포함하도록 한다. 중요한 것은 LEFT, RIGHT는 SQL 문장에 쓰여있는 테이블의 순서에 따른 다는 것이다. 다음 SQL 문장은 모두 같다:

SELECT * FROM Artists, CDs WHERE Artists.ArtistID *= CDs.ArtistID
SELECT * FROM CDs, Artists WHERE CDs.ArtistID =* Artists.ArtistID
SELECT * FROM Artists LEFT OUTER JOIN CDs ON Artists.ArtistID = CDs.ArtistID
SELECT * FROM CDs RIGHT OUTER JOIN Artists ON CDs.ArtistID = Artists.ArtistID

추측할 수 있는 것처럼, FULL OUTER JOIN은 두 테이블에서 모든 일치하지 않는 행을 결과로 포함한다.

OUTER JOIN은 총 합계 데이터 리포트를 만드는 데 특히 유용하다. Inventory(상품 목록) 테이블에 있는 각 항목에 대한 주문을 세기 위해 다음과 같은 SQL 문장을 사용할 수 있다.

SELECT Inventory.InventoryID, COUNT(Orders.OrderID)
FROM Inventory LEFT OUTER JOIN Orders
ON Inventory.InventoryID = Orders.InventoryID

GROUP BY Inventory.InventoryID

이 SQL 문장은 일치하는 주문이 없는 상품목록을 포함한 모든 상품 목록에 대한 주문 수를 센다.(이 예제는 Orders 테이블에 있는 레코드가 하나의 상품 항목에 대한 주문을 포함하고 있다고 가정한다). 이 기술을 사용하여 고객별 주문수, 벤더별 상품수, 또는 한 테이블에 어떤 열이 그에 해당하는 값을 갖고 있지 않다는 것을 아는 것이 유용한 어떤 종류의 관계에 대해서도 알 수 있다.

프리첼 자바 크레프트 동호회에서 가져왔습니다만, 원본 출처는 다른곳인거 같네요..
그리고, 명령어 부분은 mysql과 조금 틀린부분이 있습니다. 그부분은 mysql.com 에서 문서자료를 보시기 바랍니다.

셀프조인의 쉬운 예를 하나 들자면,,,
커뮤니티 사이트에서 친구등록을 할때, 나를 친구로 등록한 사람, 내가 친구로 등록한 사람은 단순 쿼리로 가능하지만, 서로 친구로 등록한 사람을 표시할때 셀프조인을 사용하게 됩니다.
대충 이런 모습이겠죠.
select a.userid from frend as a, frend as b where a.userid=b.target and b.userid = a.target;
db를 이용한 join을 잘해야 php 스크립트 내에서 스크립트로 하는 작업이 줄어들게 되면, 오류가 발생할 가능성이 줄게 됩니다.

위에 쿼리중에 한가지가 틀렸네요... 위에 쿼리는 그냥 서로서로 친구로 등록한 사람이고, 나랑 서로서로 친구한 사람이면, where 절에 and b.userid = 'myid'; 부분이 들어가야겠죠..

 

[Top]
No.
제목
작성자
작성일
조회
866SQL 의 기초 (3)
정재익
2003-10-22
12121
865SQL 의 기초 (2)
정재익
2003-10-22
12629
864SQL 의 기초 (1)
정재익
2003-10-22
15290
861SQL 에서 Join 이란...
정재익
2003-10-22
18515
860Database system 이란? [1]
정재익
2003-10-22
10554
859ACID
정재익
2003-10-22
8925
780데이터베이스 개론
정재익
2003-06-19
13689
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2020 DSN, All rights reserved.
작업시간: 0.011초, 이곳 서비스는
	PostgreSQL v13.0으로 자료를 관리합니다