문제출처 : https://www.hackerrank.com/challenges/symmetric-pairs/problem?isFullScreen=true
You are given a table, Functions, containing two columns: X and Y.
Two pairs (X1, Y1) and (X2, Y2) are said to be symmetric pairs if X1 = Y2 and X2 = Y1.
Write a query to output all such symmetric pairs in ascending order by the value of X. List the rows such that X1 ≤ Y1.
문제 자체를 이해하는데 조금 어려웠지만 문제의 내용은 다음과 같다.
"(X1,Y1) 과 같은 (X2,Y2) 를 하나의 Pair 로 보는데 여기서 X1 = Y2 , X2 = Y1 이랑 같으며, 출력할 땐 X1 이 Y1 보다 작거나 같은 경우만 출력해라"
위 문제의 Sample 을 보면 1번째 레코드와 2번째 레코드가 위 조건에 해당되고,
또 3번째 레코드와 마지막 레코드인6번째 레코드, 마지막으로 4번째,5번째 레코드가 해당한다.
즉 (Low1,Low2),(Low3,Low6),(Low4,5) 이 Pair 로 존재하니 이를 출력 조건에 맞춰 출력하면 된다.
자기 자신으로 부터 같은 쌍을 찾는 문제라 나는 처음에 SELF JOIN 을 통해 문제를 풀면 될 것 같다라고 생각이 들었다.
SELECT
*
FROM
FUNCTIONS F1
INNER JOIN
FUNCTIONS F2
ON F1.X = F2.Y AND F1.Y = F2.X
그래서 위와 같이 셀프 조인을 통한 하나의 테이블을 생성하였지만 문제에서 주어진 조건만 그대로 가져다 썼더니 다음과 같은 문제가 있었다.
위 sample 로 주어진 테이블을 예시로 보겠다.
위 조건으로 SELF JOIN 을 할경우 다음과 같은 경우 우리가 원하는 Pair 를 잘 찾을 수 있다.
X Y ----> F1.X,F1.Y,F2.X,F2.Y
20 21 20 21 21 20
21 20 21 20 20 21
하지만 서로 같은 수 이면서, 쌍이 하나인 경우는 어떻게 될 까 ?
X Y ----> F1.X,F1.Y,F2.X,F2.Y
20 21 20 21 21 20
21 20 21 20 20 21
20 20 20 20 20 20
이렇게 주어진 조건에 맞기 때문에 해당 값도 우리가 찾는 Pair 라고 찾게된다.
따라서 이러한 경우를 추가로 해결해줘야 된다.
그렇다면 이를 어떻게 해결할 수 있을까?
X = Y 인 경우와 X != Y 인 경우를 찾아 union 하는 방식으로 문제를 풀이할 수 있다.
쿼리로는 다음과 같이 작성할 수 있다.
-- x == y
SELECT *
FROM FUNCTIONS
GROUP BY X,Y
HAVING COUNT(*) = 2
-- X != Y
SELECT F1.X, F1.Y
FROM FUNCTIONS F1
INNER JOIN FUNCTIONS F2
ON F1.X = F2.Y AND F1.Y = F2.X
WHERE F1.X < F1.Y
위 쿼리처럼 X = Y 가 같을 때 두 컬럼을 기준으로 GROUP BY 하여 같으면서, 레코드가 2개인 경우를 필터링 하여 조회하고
X != Y 일 때 문제에서 주어진 조건을 그대로 적용시켜 조회한다
이제 두 테이블을 합치면 우리가 찾는 결과를 얻을 수 있다.
SELECT *
FROM FUNCTIONS
GROUP BY X,Y
HAVING COUNT(*) = 2
UNION
SELECT F1.X, F1.Y
FROM FUNCTIONS F1
INNER JOIN FUNCTIONS F2
ON F1.X = F2.Y AND F1.Y = F2.X
WHERE F1.X < F1.Y
ORDER BY X;
두 테이블을 UNION 하고 그 결과에서 문제에서 준 조건과 같이 X 값을 기준으로 정렬하여 조회하면
우리가 찾는 Pair 목록을 얻을 수 있다.
SELF JOIN 을 사용하여 테이블을 조회해본 경험이 많지 않아 이번 문제를 통해 어떨 때 사용할 수 있을지 알 수 있었고, 문제 또한 어렵지 않아 이해력을 키우는데 도움이 되었다.