SQL Problems - Select, Basic Joins, Basic Aggregations

SQL Problems - Select, Basic Joins, Basic Aggregations

Select

584. Find Customer Referee

  • referee_id๊ฐ€ 2๊ฐ€ ์•„๋‹Œ row์˜ name์„ selectํ•œ๋‹ค.
  • ๋ฌธ์ œ๋Š” referee_id ์— null value๋ฅผ ํฌํ•จํ•œ ๊ฒฝ์šฐ์—๋Š” select์—์„œ ์ œ์™ธ๋œ๋‹ค๋Š” ์ ์ด๋‹ค.
  • ๋”ฐ๋ผ์„œ null value๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ์กฐ๊ฑด referee_id IS NULL ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.
SELECT name FROM Customer WHERE referee_id IS NULL or referee_id != 2

1148. Article Views I

  • author_id๋ฅผ ๊ธฐ์ค€์œผ๋กœ unique ํ•œ ๊ฐ’๋งŒ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด DISTINCT keyword๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
  • ์ถœ๋ ฅ๋˜๋Š” column์˜ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด AS ์ ˆ origin_col AS new_col ์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ํŠน์ • column์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•˜๋ ค๋ฉด ORDER BY ์ ˆ์„ ์‚ฌ์šฉํ•œ๋‹ค.
SELECT DISTINCT author_id AS id FROM Views WHERE author_id = viewer_id ORDER BY author_id ASC

1683. Invalid Tweets

  • column ๊ฐ’์˜ ๊ธธ์ด๋ฅผ ๊ตฌํ•˜๋ ค๋ฉด length ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
SELECT tweet_id FROM Tweets WHERE length(content) > 15

Basic Joins

1378. Replace Employee ID With The Unique Identifier

  • Employees table์„ ๊ธฐ์ค€์œผ๋กœ ํ•˜๋ฏ€๋กœ LEFT JOIN ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
SELECT EmployeeUNI.unique_id, name FROM Employees LEFT JOIN EmployeeUNI ON Employees.id = EmployeeUNI.id
  • JOIN ์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ์‹์— ๋Œ€ํ•œ ์„ค๋ช…์€ ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•œ๋‹ค.
notion image

1581. Customer Who Visited but Did Not Make Any Transactions

  • LEFT EXCLUDING JOIN ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
    • LEFT EXCLUDING JOIN ์€ LEFT JOIN์„ ์‚ฌ์šฉํ•˜๋˜ right table์— ํ•ญ๋ชฉ์ด ์žˆ๋Š” row๋ฅผ ์ œ์™ธํ•ด์•ผ ํ•˜๋ฏ€๋กœ WHERE ์ ˆ๋กœ Right.key IS NULL ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.
  • count๋ฅผ customer_id ๊ธฐ์ค€์œผ๋กœ ํ•ด์•ผํ•˜๋ฏ€๋กœ GROUP BY ์ ˆ์„ ์‚ฌ์šฉํ•œ๋‹ค.
SELECT customer_id, COUNT(Visits.visit_id) AS count_no_trans FROM Visits LEFT JOIN Transactions ON Visits.visit_id = Transactions.visit_id WHERE Transactions.visit_id IS NULL GROUP BY customer_id

197. Rising Temperature

  • ์ด์ „๊ฐ’์€ LAG ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
    • LAG(column) OVER (ORDER BY order_column)
  • ๋ฌธ์ œ๋Š” LAG ํ•จ์ˆ˜๋Š” WHERE ์ ˆ์—์„œ ์“ธ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ sub query๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ด์ „๊ฐ’์„ ์ฐธ์กฐํ•˜๋Š” column์„ ์ƒ์„ฑํ•œ๋‹ค.
    • sub query ์ƒ์„ฑ ์‹œ ๋ฐ˜๋“œ์‹œ ์ด๋ฆ„์„ ๋ถ™์—ฌ์ฃผ์–ด์•ผ ํ•œ๋‹ค.
SELECT id FROM ( SELECT id, temperature AS currTemp, LAG(temperature) OVER (ORDER BY recordDate) AS prevTemp, DATEDIFF( recordDate, LAG(recordDate) OVER (ORDER BY recordDate) ) AS recordDateDiff FROM Weather ) WeatherWithPrev WHERE currTemp > prevTemp AND recordDateDiff = 1

1661. Average Time of Process per Machine

  • activity_type์œผ๋กœ ๊ตฌ๋ถ„๋˜๋Š” ์‹œ์ž‘, ์ข…๋ฃŒ row๋ฅผ ๋ฌถ์–ด์„œ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.
    • LAG OVER ์ ˆ์—์„œ PARTITION BY ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ machine_id, process_id ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฌถ์–ด์ค„ ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
    • activity_type์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•œ๋‹ค.
  • ํ‰๊ท ๊ฐ’์„ ๊ตฌํ•˜๋˜ 3์ž๋ฆฌ๋งŒ ๋‚จ๊ธธ ์ˆ˜ ์žˆ๋„๋ก ROUND ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
SELECT machine_id, ROUND(AVG(end_time - start_time), 3) as processing_time FROM ( SELECT machine_id, process_id, LAG(timestamp) OVER ( PARTITION BY machine_id, process_id ORDER BY activity_type ) AS start_time, timestamp AS end_time FROM Activity ) ActivityPair GROUP BY machine_id

1280. Students and Examinations

  • ํ•ด๋‹ต์˜ ๋„์›€์„ ๋ฐ›์•˜๋˜ ๋ฌธ์ œ. ๋ค์œผ๋กœ JOIN ํ•  ๋•Œ ํ…Œ์ด๋ธ” ์ด๋ฆ„์„ ์ถ•์•ฝํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ข€ ๋ฐฐ์› ๋‹ค.
  • ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์„ JOIN ํ•  ๋•Œ๋Š” ๊ธฐ์ค€์„ ์ž˜ ์žก๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๋Š” ๋ฌธ์ œ์˜€๋‹ค.
  • ์•„๋ž˜์™€ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ ‘๊ทผํ•˜๋ฉด ์‰ฝ๊ฒŒ ์ดํ•ด๋  ์ˆ˜ ์žˆ๋‹ค.
    • ๋จผ์ € ์ด ๋ฌธ์ œ๋Š” ๊ฐ ํ•™์ƒ Students x ๊ณผ๋ชฉ Subjects ์˜ ์กฐํ•ฉ์„ ๊ธฐ์ค€์œผ๋กœ ์ฐธ์—ฌํ•œ ์‹œํ—˜์˜ ์ˆซ์ž๋ฅผ ์‹œํ—˜ ๊ธฐ๋ก Examinations ์—์„œ ์„ธ์–ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค.
    • ๋”ฐ๋ผ์„œ ๊ธฐ์ค€์€ Students ์˜ Subjects ์กฐํ•ฉ์ด ๋˜์–ด์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ๊ตฌํ•˜๋ ค๋ฉด CROSS JOIN์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‘ ํ…Œ์ด๋ธ”์˜ row์˜ ์กฐํ•ฉ์„ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.
    • ์ด์ œ ์ด๋ ‡๊ฒŒ ๊ธฐ์ค€์ ์ด ์žกํ˜”๋‹ค๋ฉด ์‹œํ—˜ ๊ธฐ๋ก Examinations์„ LEFT JOIN ํ•˜์—ฌ ๊ธฐ์ค€์ ์— ๋”ฐ๋ผ counting์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
    • student_id, subject_name ๋งˆ๋‹ค counting ํ•  ์ˆ˜ ์žˆ๋„๋ก GROUP BY๋ฅผ ์ ์šฉํ•œ๋‹ค.
    • ์ •๋ ฌ์ด ํ•„์š”ํ•˜๋ฏ€๋กœ ORDER BY๋ฅผ ์ ์šฉํ•œ๋‹ค.
SELECT S.student_id, S.student_name, SUB.subject_name, COUNT(E.subject_name) AS attended_exams FROM Students S CROSS JOIN Subjects SUB LEFT JOIN Examinations E ON ( S.student_id = E.student_id AND SUB.subject_name = E.subject_name ) GROUP BY S.student_id, SUB.subject_name ORDER BY S.student_id, SUB.subject_name

570. Managers with at Least 5 Direct Reports

  • ๋จผ์ € managerId๋ฅผ ๊ธฐ์ค€์œผ๋กœ report ์ˆซ์ž (row ์ˆซ์ž)๋ฅผ ์„ผ๋‹ค.
  • ๊ทธ๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ์ค€์œผ๋กœ manager์˜ ์ด๋ฆ„ name ์„ JOIN ํ•˜์—ฌ ๊ฐ€์ ธ์˜จ๋‹ค.
  • ์ „์ฒด ๊ฒฐ๊ณผ์—์„œ report ์ˆซ์ž, ์ด๋ฆ„์ด ์—†๋Š” ๊ฒฝ์šฐ๋ฅผ ์ œ์™ธํ•œ๋‹ค (WHERE ์ ˆ).
SELECT B.name FROM ( SELECT managerId, COUNT(managerId) as report FROM Employee GROUP BY managerId ) E LEFT JOIN Employee B ON E.managerId = B.id WHERE E.report >= 5 AND B.name IS NOT NULL

1934. Confirmation Rate

  • ์‚ฌ์šฉ์ž ID user_id ๋ฅผ ๊ธฐ์ค€์œผ๋กœ confirmation rate๋ฅผ ๊ตฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ Signups table์ด ๊ธฐ์ค€์ด ๋˜์–ด์•ผ ํ•œ๋‹ค.
  • Confirmation rate๋ฅผ ๊ตฌํ•˜๋ ค๋ฉด ์ „์ฒด action ์ˆซ์ž์™€ confirmed ๋œ action ์ˆซ์ž๋ฅผ ๋”ฐ๋กœ ๊ตฌํ•ด์•ผ ํ•œ๋‹ค.
    • CASE ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ action column ๊ฐ’์ด confirmed ์ธ ๊ฒƒ๋งŒ ๊ฐ’์„ 1, ๋‚˜๋จธ์ง€๋Š” NULL๋กœ ํ•˜์—ฌ COUNT์—์„œ action = confirmed ์ธ ๊ฒƒ๋งŒ ์…€ ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ๊ตฌํ•œ ์ˆซ์ž๋ฅผ user_id ๊ธฐ์ค€์œผ๋กœ JOIN ํ•œ๋‹ค.
  • Confirmation rate๋ฅผ ๊ณ„์‚ฐํ•˜๋˜ ๊ฐ’์ด NULL ์ธ ๊ฒฝ์šฐ 0์„ ๋Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋„๋ก COALESCE ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
    • COALESCE ํ•จ์ˆ˜๋Š” ์ธ์ž๋กœ ๋“ค์–ด์˜จ ๊ฐ’ ์ค‘ NULL์ด ์•„๋‹Œ ์ฒซ๋ฒˆ์งธ ๊ฐ’์„ ๋Œ๋ ค์ค€๋‹ค.
  • ์†Œ์ˆ˜์  2์ž๋ฆฌ๋กœ ์˜ฌ๋ฆผํ•˜์—ฌ ๊ตฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ ROUND ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ๋‹ค.
# Write your MySQL query statement below SELECT S.user_id, ROUND(COALESCE(C.count / C.total, 0), 2) as confirmation_rate FROM Signups S LEFT JOIN ( SELECT user_id, COUNT(CASE action WHEN 'confirmed' THEN 1 ELSE NULL END) as count, COUNT(*) as total FROM Confirmations GROUP BY user_id ) C ON S.user_id = C.user_id

Basic Aggregations

1251. Average Selling Price

  • Prices์— ๊ธฐ์žฌ๋œ ์ œํ’ˆ ID product_id ๊ฐ€ ๊ธฐ์ค€์ด ๋˜์–ด์•ผ ํ•œ๋‹ค.
  • ํŒ๋งค๋œ ์ œํ’ˆ ๊ธฐ๋ก UnitsSold ๊ณผ ์ œํ’ˆ ID product_id ๋ฟ ์•„๋‹ˆ๋ผ ๊ธฐ๊ฐ„ start_date, end_date, purchase_date๋„ ๋งž์•„์•ผ ํ•˜๋ฏ€๋กœ ํ•ด๋‹น ์กฐ๊ฑด์„ ๋ชจ๋‘ ํฌํ•จํ•˜์—ฌ JOIN ํ•œ๋‹ค.
  • ๊ฐ’์ด NULL์ธ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด COALESCE ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
SELECT P.product_id, ROUND(COALESCE(SUM(U.units * P.price) / SUM(U.units), 0), 2) as average_price FROM Prices P LEFT JOIN UnitsSold U ON U.product_id = P.product_id AND U.purchase_date >= P.start_date AND U.purchase_date <= P.end_date GROUP BY P.product_id

1193. Monthly Transactions I

  • ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ฑฐ๋ž˜์˜ ์ˆซ์ž, ๊ฑฐ๋ž˜๋Ÿ‰์„ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ.
  • ๋ ˆ์ฝ”๋“œ์˜ ์ˆซ์ž๋ฅผ ์…€ ๋•Œ๋Š” CASE๋ฌธ์„ ์“ฐ๋˜ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•  ๋•Œ๋Š” ์•„๋ฌด ๊ฐ’ (์˜ˆ: 1) ์•„๋‹๋•Œ๋Š” NULL์ด ๋˜๋„๋ก ํ•œ๋‹ค (ELSE ์ƒ๋žต).
  • ๋ ˆ์ฝ”๋“œ ๊ฐ’์„ ํ•ฉํ• ๋•Œ๋Š” CASE๋ฌธ์„ ์“ฐ๋˜ ํ•„๋“œ ELSE 0๋กœ ์กฐ๊ฑด์„ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค.
    • ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์กฐ๊ฑด์— ํ•ด๋‹น๋˜๋Š” ๋ ˆ์ฝ”๋“œ๊ฐ€ ํ•˜๋‚˜๋„ ์—†์„ ๊ฒฝ์šฐ ๊ฐ’์ด NULL์ด ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
    • COALESCE๋ฅผ ์กฐํ•ฉํ•  ์ˆ˜๋„ ์žˆ๊ฒ ์ง€๋งŒ ์ง๊ด€์ ์ด์ง€๋Š” ์•Š๋‹ค.
SELECT DATE_FORMAT(T.trans_date, '%Y-%m') as month, T.country, COUNT(*) AS trans_count, COUNT(CASE WHEN T.state = "approved" THEN 1 END) AS approved_count, SUM(T.amount) AS trans_total_amount, SUM(CASE WHEN T.state = "approved" THEN T.amount ELSE 0 END) AS approved_total_amount FROM Transactions AS T GROUP BY month, T.country

1174. Immediate Food Delivery II

  • ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ณจ๋ผ์„œ ๊ฐ’์„ ์š”์•ฝํ•ด์•ผ ํ•œ๋‹ค.
  • ๋จผ์ € ์—ฌ๊ธฐ์„œ๋Š” ๊ณ ๊ฐ๋ณ„ ์ฒซ๋ฒˆ์งธ ์ฃผ๋ฌธ์„ ๊ณจ๋ผ๋‚ด์•ผ ํ•˜๋ฏ€๋กœ customer_id๋กœ ๊ทธ๋ฃนํ•‘๋œ order_date์˜ ์ตœ์†Œ๊ฐ’์„ ๊ตฌํ•ด์•ผ ํ•œ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ์–ป์–ด์ง„ ๊ฒฐ๊ณผ๋ฅผ customer_id, order_date๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์›๋ž˜ ํ…Œ์ด๋ธ”๊ณผ INNER JOINํ•˜์—ฌ ๋‚˜๋จธ์ง€ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.
SELECT ROUND( COUNT( CASE WHEN order_date = customer_pref_delivery_date THEN 1 END ) * 100 / COUNT(*), 2 ) AS immediate_percentage FROM Delivery AS D JOIN ( SELECT customer_id, MIN(order_date) AS first_date FROM Delivery GROUP BY customer_id ) F ON D.customer_id = F.customer_id AND D.order_date = F.first_date
  • WHERE IN ์ ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์˜ ๋‚ด์šฉ์„ ์ข€ ๋” ์ถ•์•ฝํ•ด์„œ ํ‘œํ˜„ ๊ฐ€๋Šฅํ•˜๋‹ค.
    • WHERE (์ผ์น˜ํ•ด์•ผ๋  column ๋ชฉ๋ก) IN (์„œ๋ธŒ ์ฟผ๋ฆฌ)
SELECT ROUND( COUNT( CASE WHEN order_date = customer_pref_delivery_date THEN 1 END ) * 100 / COUNT(*), 2 ) AS immediate_percentage FROM Delivery AS D WHERE (customer_id, order_date) IN ( SELECT customer_id, MIN(order_date) AS order_date FROM Delivery GROUP BY customer_id )

550. Game Play Analysis IV

  • ๋ฌธ์ œ์˜ ์กฐ๊ฑด(์ฒซ๋ฒˆ์งธ ๋กœ๊ทธ์ธ ๋‚ ์งœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์—ฐ์† 2์ผ ๋กœ๊ทธ์ธํ•œ ํ”Œ๋ ˆ์ด์–ด)์„ ์ œ๋Œ€๋กœ ํ™•์ธํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค.
  • ๊ฐ ํ”Œ๋ ˆ์ด์–ด ๋ณ„ ์ฒซ๋ฒˆ์งธ ๋กœ๊ทธ์ธ ๋‚ ์งœ๋ฅผ ๊ตฌํ•˜๊ณ  player_id๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์›๋ž˜ ํ…Œ์ด๋ธ”๊ณผ INNER JOIN ํ•œ๋‹ค.
  • ์ „์ฒด ํ”Œ๋ ˆ์ด์–ด์˜ ์ˆ˜, ๊ทธ๋ฆฌ๊ณ  ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ํ”Œ๋ ˆ์ด์–ด์˜ ์ˆ˜๋ฅผ ์„ผ๋‹ค.
  • ๋ฌธ์ œ๋Š” ๋™์ผํ•œ player_id๋ฅผ ๊ฐ€์ง„ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ ์กด์žฌํ•˜๋ฏ€๋กœ DISTINCT ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ uniqueํ•œ ํ”Œ๋ ˆ์ด์–ด์˜ ์ˆ˜๋ฅผ ์„ธ์•ผ ํ•œ๋‹ค.
  • COUNT + CASE๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ์—๋„ ์•ž์ชฝ์— DISTINCT๋ฅผ ๋ถ™์—ฌ์„œ unique ํ•œ ๊ฐ’์„ ์…€ ์ˆ˜ ์žˆ๋‹ค.
    • CASE ๋ฌธ ๋‚ด๋ถ€์— DISTINCT๋ฅผ ๋ถ™์ด๋ฉด ์ œ๋Œ€๋กœ ์ฒดํฌ๊ฐ€ ์•ˆ๋œ๋‹ค. ๋ฐ˜๋“œ์‹œ ๊ฐ€์žฅ ์•ž์— ๋ถ™์—ฌ์•ผ ํ•œ๋‹ค.
SELECT ROUND( COUNT( DISTINCT CASE WHEN DATEDIFF(A.event_date, F.first_date) = 1 THEN A.player_id END ) / COUNT(DISTINCT A.player_id), 2 ) as fraction FROM Activity AS A JOIN ( SELECT player_id, MIN(event_date) AS first_date FROM Activity GROUP BY player_id ) F ON A.player_id = F.player_id
ย