인턴 생활이 시작되고도 벌써 5일이 지난 지금
아직까지 적응하고있는 중이지만 틈틈히 SQL에 관한 포스팅도 올려보려 한다.
이번 시리즈는 Leetcode
라는 해외의 유명한 문제풀이 사이트로
몇 대기업의 코딩테스트 문제도 여기서 갖고 온다는 얘기가 있다.
그리고 일단 무자본인 우리네들에게 가장 좋은 SQL 친구인
MySQL 쿼리를 공부할 수 있는 좋은 곳이기도 하다.
그러므로 우리는 저 위의 사진에서 SQL I. 만 볼거다 ㅎㅎ
(근데 회사에서는 Oracle
쓴다..! OMG)
일단 Day 1은 4문제가 있는데 앞의 두 문제는 너무 쉬워
뒤의 두 문제만 올려보도록 하겠다.
또한
이제 여기서 주의할 점이 있다.
맨 처음 나는 Python에서 고전을 면치 못하고 있었기에
Leetcode에서의 문제들을 띠엄띠엄 풀고 있었다.
하지만 제목에서 보다시피 Day 숫자
가 붙는 데에는 다 이유가 있는 법!
일단, 하루에 Day가 하나씩 열리고 그것을 다 풀면
그 다음 Day가 다음날에 열린다.
하지만 이 싸이클을 놓친다면...?
처음부터 다시 시작해야한다!!!
따라서 Leetcode에서 공짜 문제를 풀 때는
평균 3문제 밖에 되지 않으니 꼭! 시간을 내어 하루에 Day 하나씩 풀어야 한다.
안그러면 다시 처음부터 해야한다...
그리고 일단 영어다...
해석이 되지 않는다면 여기 문제에서 제공해주는
Input & Output
을 적극적으로 이용하도록 하자.
Write an SQL query to report the names of the customer that are not referred by the customer with id = 2
.
Return the result table in any order.
The query result format is in the following example.
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| id | int |
| name | varchar |
| referee_id | int |
+-------------+---------+
id is the primary key column for this table.
Each row of this table indicates the id of a customer, their name, and the id of the customer who referred them.
Input:
Customer table:
+----+------+------------+
| id | name | referee_id |
+----+------+------------+
| 1 | Will | null |
| 2 | Jane | null |
| 3 | Alex | 2 |
| 4 | Bill | null |
| 5 | Zack | 1 |
| 6 | Mark | 2 |
+----+------+------------+
Output:
+------+
| name |
+------+
| Will |
| Jane |
| Bill |
| Zack |
+------+
문제를 보면 referee_id
가 2가 아닌 것을 출력해야하므로
referee_id
가 1이거나 null
값인 것을 출력해야한다.
-- Customer 테이블에서 name을 출력하는데
SELECT name FROM Customer
-- referee_id가 2가 아니거나 null값인 것을 출력해라
WHERE referee_id <> 2 OR referee_id IS NULL;
/* 또는
WHERE referee_id == 1 OR referee_id IS NULL; */
>>> {"headers": ["name"], "values": [["Will"], ["Jane"], ["Bill"], ["Zack"]]}
여기서 WHERE절에 OR
가 들어가는 이유는
SQL에서의 AND
개념은 합집합이기 때문이다.
그리하여
WHERE referee_id <> 2 AND referee_id IS NULL
구문 이었다면 referee_id가 2와 NULL이 동시에 아닌 값을 찾는 것이므로
답이 나오지 않는다.
Write an SQL query to report all customers who never order anything.
Return the result table in any order.
The query result format is in the following example.
+-------------+------+
| Column Name | Type |
+-------------+------+
| id | int |
| customerId | int |
+-------------+------+
id is the primary key column for this table.
customerId is a foreign key of the ID from the Customers table.
Each row of this table indicates the ID of an order and the ID of the customer who ordered it.
Input:
Customers table:
+----+-------+
| id | name |
+----+-------+
| 1 | Joe |
| 2 | Henry |
| 3 | Sam |
| 4 | Max |
+----+-------+
Orders table:
+----+------------+
| id | customerId |
+----+------------+
| 1 | 3 |
| 2 | 1 |
+----+------------+
Output:
+-----------+
| Customers |
+-----------+
| Henry |
| Max |
+-----------+
아무것도 시키지 않는 사람들의 이름을 불러오면 된다.
하지만 Customers
테이블과 Orders
테이블을 같이 봐야하므로
이 문제를 해결해야한다.
여기서는 내가 짠 쿼리와 Discussion에 올라온 풀이 쿼리를 같이 소개해보겠다.
-- Customers 에서 name을 뽑는데
SELECT name FROM Customers
-- Orders와 조인하고
LEFT JOIN Orders
-- 서로의 id를 기준으로 조인한다.
ON Customers.id = Orders.id
-- 그 중에서 customers의 id와 orders의 customerId와 다른 것을 출력한다.
WHERE customers.id <> orders.customerId;
>>> {"headers": ["name"], "values": [["Joe"], ["Henry"]]}
-- Customers 테이블에서 name을 customer로 이름 붙혀 가져오는데
SELECT name AS customers
FROM customers
-- 그 중에서 id가 존재하지 않는 (어디에서?)
WHERE id NOT IN
-- Orders 테이블의 customerId 값에서
(SELECT customerId FROM Orders); -- Sub-Query
이제 Day 2로 넘어가보자.