오늘은 SQL을 다루면서 있었던 문제에 대해서 설명하면서, 어떻게 해결해나갈지 고민해보겠다.
아래 Table들이 있다고 하자.
상황은 아래와 같다.
1. 모든 Servers의 목록을 보여준다. 단, Login user가 각각의 Server에 접근권한(Permission)이 있는 경우에만 Server에 Login할 수 있는 ID와 PW를 볼 수 있다. (권한이 없으면 No permission 이라고 띄운다.)
2. ServersPermissions의 PK는 ServerName과 PermitTo를 합친 것이다.
3. 하나의 Server에는 여러 users가 권한(Permission)을 가질 수 있다. 즉, ServersPermissions Table에는 하나의 serverName과 여러 User가 매칭된다는 것이다.
4. login user의 정보는 SessionID와 비교한다.
5. SP(Stored Precedure)를 사용할 수 있다.
자! SQL문을 만들어보세요.
나의 접근 방법은 아래와 같았다.
먼저 Server를 불러오는게 중점이니 아래처럼 시작한다.
SELECT * FROM Servers;
다음으로, Servers의 ID/PW를 Permissions에 따라 다르게 보여줘야하니 Servers와 ServersPermissions를 ServerName을 가지고 JOIN한다. 이 때, Servers의 table은 모두 나와야하니 INNER JOIN이 아니라, LEFT OUTER JOIN을 해본다.
SELECT * FROM Servers AS SV LEFT OUTER JOIN ServersPermissions AS SP ON (SV.ServerName = SP.ServerName);
물론 WHERE 를 넣어서 조건을 좀더 넣어줘야하지만, WHERE 를 넣기 전부터 이미 문제가 있다.
어떤 문제냐 하면,
예를 들어 server1이 있다고 치자. 그리고 이 server1에 접근할 수 있는 user가 10명이라 치자.
그럼 벌써 위의 SELECT문에서 결과 rows가 10개가 나와버린다. 왜? server1에 server1을 가진 permitTo(user)를 join 했기 때문에...
이 10개의 rows를 모두 보여줄 것인가? 아니다. 그래서 이를 방지하기 위해 중복값을 제거해주는 걸 찾아본다.
DISTINCT나 GROUP BY!!
해결책이 될 것만 같다! 하지만 자료를 찾아보면 알겠지만 DISTINCT나 GROUP BY는 사용하는데 제약이 좀 있다.
여러 SELECT 값에 대해서 적용하기 쉽지 않다는 걸.. 찾아보라. 예를 들어 GROUP BY는 쓰려면 aggregate 가 안 들어간 모든 column에 대해서 grouping을 해줘야한다는 등!
(여담이지만, 위의 SELECT의 결과는 사실 중복데이터도 아니다. columns을 잘 살펴보면 같은 값이 많겠지만, 몇 개의 columns는 다른 값을 가진다. 이런 경우에는 DISTINCT도 못 쓴다. 엄연히 다른 rows이기 때문!)
여기서 각설하고, 다시 문제로 돌아간다면!
왜? 하나의 row가 아닌 10개의 rows가 나와버릴까?
이 문제는 Join의 특성에 대한 것이다. Join을 할 때는, PK와 FK를 연관 짓는게 좋다. 안 그러면 위처럼 semi중복? 데이터가 생기기 때문이다.
따라서, ON에 PK와 FK 등의 유일한 값. 즉! 두 table을 1:1 matching할 수 있는 것을 넣어야한다.
다시 위의 테이블을 보면, ServersPermissions의 PK가 ServerName과 PermitTo를 합쳐서 PK로 사용하기 때문에, 이런 문제가 생긴 것이다.
(여담, PK는 유일값이라는 얘기 때문에 보통 1개의 column으로만 해야한다고들 알고 있지만, 다중 column을 묶어서 PK로 만들 수 있다. 위의 ServersPermissions 테이블처럼... 이런 경우의 PK를 Composite Key라고 한다.)
다시 본론으로 돌아와서, 그렇다면 이런 경우에 어떻게 JOIN을 해야할까? 아니면 아예 JOIN을 하면 안 될까?
흐음.. 그 답은 다음에 다시 돌아오겠다!
물론 내가 한 방법이 정답은 아니다. 오히려 내 솔루션을 보고, 나조차도 그렇게 효율적인 query라고 생각하지 않았다.
다만, 결과가 나와야하기 때문에 약간의 억지를 부려서 만들어봤다. 자신만의 결과를 만들어보고 좋다고 생각하면 공유해주길 바란다.
2020/11/11 - [개발/DBMS] - JOIN 문제 해결
'개발 > DBMS' 카테고리의 다른 글
JOIN 문제 해결 (0) | 2020.11.11 |
---|---|
문자+숫자 DB 컬럼 정렬하기 (0) | 2020.11.09 |
RDBMS 정규화(Normalization) - 2/2 (0) | 2020.09.27 |
RDBMS 정규화(Normalization) - 1/2 (2) | 2020.09.24 |
Stored Procedure - 저장 프로시저 (0) | 2020.08.11 |
댓글