난이도: EASY
문제
Table: Visits
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| visit_id | int |
| customer_id | int |
+-------------+---------+
visit_id is the column with unique values for this table.
This table contains information about the customers who visited the mall.
Table: Transactions
+----------------+---------+
| Column Name | Type |
+----------------+---------+
| transaction_id | int |
| visit_id | int |
| amount | int |
+----------------+---------+
transaction_id is column with unique values for this table.
This table contains information about the transactions made during the visit_id.
Write a solution to find the IDs of the users who visited without making any transactions and the number of times they made these types of visits.
Return the result table sorted in any order.
The result format is in the following example.
Example 1:
Input:
Visits
+----------+-------------+
| visit_id | customer_id |
+----------+-------------+
| 1 | 23 |
| 2 | 9 |
| 4 | 30 |
| 5 | 54 |
| 6 | 96 |
| 7 | 54 |
| 8 | 54 |
+----------+-------------+
Transactions
+----------------+----------+--------+
| transaction_id | visit_id | amount |
+----------------+----------+--------+
| 2 | 5 | 310 |
| 3 | 5 | 300 |
| 9 | 5 | 200 |
| 12 | 1 | 910 |
| 13 | 2 | 970 |
+----------------+----------+--------+
Output:
+-------------+----------------+
| customer_id | count_no_trans |
+-------------+----------------+
| 54 | 2 |
| 30 | 1 |
| 96 | 1 |
+-------------+----------------+
Explanation:
Customer with id = 23 visited the mall once and made one transaction during the visit with id = 12.
Customer with id = 9 visited the mall once and made one transaction during the visit with id = 13.
Customer with id = 30 visited the mall once and did not make any transactions.
Customer with id = 54 visited the mall three times. During 2 visits they did not make any transactions, and during one visit they made 3 transactions.
Customer with id = 96 visited the mall once and did not make any transactions.
As we can see, users with IDs 30 and 96 visited the mall one time without making any transactions. Also, user 54 visited the mall twice and did not make any transactions.
솔직히 처음에 문제 이해를 못했음. 아니 제대로 했는데 예시보다가 혼란이 와서 내가 이해한게 맞는지 챗지한테 물어봄. 근데 맞긴했다.
Write a solution to find the IDs of the users who visited without making any transactions
어떤 트랜잭션도 만들지 않은 사용자의 ID를 찾아라.
=> 트랜잭션 테이블에 없는 visit_id를 찾는다.(대신 보여줄 값은 customer_id)
=> LEFT JOIN 걸어서 트랜잭션 테이블에 없는 visit_id를 찾아 방문 테이블의 customer_id 를 SELECT
and the number of times they made these types of visits.
그리고 몇 번 그들이 이런 류의 방문(트랜잭션을 만들지 않은 방문)을 했는지 찾아라.
=> 방문 테이블의 고객별로 집계하여 visit_id 개수를 센다
=> customer_id 를 기준으로 그룹핑해 visit_id 개수를 센다. (COUNT()함수는 NULL은 세지 않음.)
시도
SELECT customer_id, count_no_trans
FROM Visits A LEFT OUTER JOIN Transactions B
ON A.visit_id = B.visit_id
WHERE B.visit_id IS NULL
count_no_trans 에 대한 연산 빼먹음.
나의 최종 제출 답안:
SELECT customer_id, COUNT(A.visit_id) AS count_no_trans
FROM Visits A LEFT OUTER JOIN Transactions B
ON A.visit_id = B.visit_id
WHERE B.visit_id IS NULL
GROUP BY A.customer_id
chatGPT에게 더 간단하고 효율적이게 수정해달라고 요청한 답안:
✅ 더 효율적인 방법 (서브쿼리 사용)
SELECT customer_id, COUNT(visit_id) AS count_no_trans
FROM Visits
WHERE visit_id NOT IN (SELECT visit_id FROM Transactions)
GROUP BY customer_id;
✅ 왜 이 방법이 더 효율적일까?
방법 | 장점 | 단점 |
LEFT JOIN + WHERE IS NULL (기존 쿼리) | ✅ JOIN을 활용하여 가독성이 좋음 | ❌ JOIN 연산이 크면 성능 저하 가능 |
NOT IN (SELECT ...) (최적화 쿼리) | ✅ JOIN을 하지 않고 Transactions에서 직접 조회하여 필터링 | ❌ Transactions 테이블이 크다면 서브쿼리 실행이 느릴 수 있음 |
🔍 성능 비교
1️⃣ 기존 LEFT JOIN + WHERE IS NULL 방식
- 장점: SQL 쿼리가 직관적이고 가독성이 좋음.
- 단점: JOIN을 수행한 후, NULL 값을 필터링해야 하므로 JOIN 연산이 크면 성능이 떨어질 수 있음.
- 시간 복잡도: O(N log M) (N: Visits, M: Transactions)
2️⃣ NOT IN (SELECT ...) 방식
- 장점: JOIN을 사용하지 않고 직접 Transactions 테이블에서 제외할 값을 찾음.
- 단점: NOT IN이 실행될 때, 서브쿼리가 크다면 전체 조회(Full Table Scan)가 발생할 수도 있음.
- 시간 복잡도: O(N), 인덱스가 있다면 O(log M)
✅ 최적의 성능을 위한 인덱스 추가
서브쿼리 방식(NOT IN)을 사용할 때는 Transactions.visit_id에 인덱스를 추가하면 훨씬 빠르게 실행됩니다.
CREATE INDEX idx_visit_id ON Transactions (visit_id);
✅ 이 인덱스를 추가하면 SELECT visit_id FROM Transactions의 실행 속도가 크게 향상됩니다.
🚀 최종 추천
데이터 크기추천 쿼리
데이터가 많지 않다면 (<100K rows) | ✅ NOT IN (SELECT visit_id FROM Transactions) |
데이터가 많다면 (>100K rows) | ✅ LEFT JOIN + WHERE IS NULL |
✅ 소규모 데이터에서는 NOT IN이 더 빠를 수 있고, 대규모 데이터에서는 LEFT JOIN이 더 적합함! 🚀
'Coding Challenges > LeetCode' 카테고리의 다른 글
[Java] 28. Find the Index of the First Occurrence in a String (1) | 2025.02.14 |
---|---|
[SQL50] 197. Rising Temperature (0) | 2025.02.13 |
[SQL50] 1068. Product Sales Analysis I (0) | 2025.02.11 |
[Java] 27. Remove Element (0) | 2025.02.11 |
[SQL50] 1378. Replace Employee ID With The Unique Identifier (0) | 2025.02.11 |