๐Ÿ‹ โšพ๏ธ ๐Ÿ’ป ๐ŸŽฌ ๐ŸŽฎ

coding_test/SQL ๋ฌธ์ œ

[LeetCode] 550. Game Play Analysis IV (AGGREGATE)

aeightchill 2025. 3. 14. 23:23
728x90

๐Ÿ—‚๏ธ  ๋ฌธ์ œ

[SQL50] 550. Game Play Analysis IV (AGGREGATE)



โœ๐Ÿป  ํ’€์ด

 

๋ฌธ์ œ ํ•ด์„

์œ ์ €๊ฐ€ ์ฒซ ๋กœ๊ทธ์ธํ•œ ๋‹ค์Œ๋‚  ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•œ ๋น„์œจ์„ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ

 

๐Ÿ“Œ  Table : Activity

Column Name Type ์„ค๋ช…
player_id int ์œ ์ €์˜ ๊ณ ์œ  ID
device_id int ์œ ์ €๊ฐ€ ๋กœ๊ทธ์ธํ•œ ์žฅ์น˜์˜ ID
event_date date ๋กœ๊ทธ์ธ ๋‚ ์งœ
games_played int ํ•ด๋‹น ๋กœ๊ทธ์ธ ๋™์•ˆ ํ”Œ๋ ˆ์ดํ•œ ๊ฒŒ์ž„ ์ˆ˜ (0์ผ ์ˆ˜๋„ ์žˆ์Œ)

 

  • PRIMARY KEY  :  (player_id, event_date)
    • ํ•œ ์œ ์ €(player_id)๊ฐ€ ๊ฐ™์€ ๋‚ (event_date)์— ์—ฌ๋Ÿฌ ๋ฒˆ ๋กœ๊ทธ์ธํ•œ ๊ธฐ๋ก์€ ์—†๋‹ค.

 

๐Ÿ“Œ  ์š”๊ตฌ ์‚ฌํ•ญ

  1. ๊ฐ ์œ ์ €์˜ ์ฒซ ๋กœ๊ทธ์ธ ๋‚ ์งœ(first_login)๋ฅผ ์ฐพ๋Š”๋‹ค.
  2. ์ฒซ ๋กœ๊ทธ์ธ ๋‚ ์งœ์˜ ๋‹ค์Œ๋‚ (first_login + 1์ผ)์—๋„ ๋กœ๊ทธ์ธํ•œ ์œ ์ €๋ฅผ ์ฐพ๋Š”๋‹ค.
  3. ์ด๋Ÿฌํ•œ ์œ ์ € ์ˆ˜๋ฅผ ์ „์ฒด ์œ ์ € ์ˆ˜๋กœ ๋‚˜๋ˆ„์–ด ๋น„์œจ์„ ๊ตฌํ•œ๋‹ค.
  4. ๊ฒฐ๊ณผ๋ฅผ ์†Œ์ˆ˜์  ๋‘˜์งธ ์ž๋ฆฌ๊นŒ์ง€ ๋ฐ˜์˜ฌ๋ฆผ(ROUND(..., 2)) ํ•œ๋‹ค.

 

 

์ฝ”๋“œ

-- ์ฒซ ๋กœ๊ทธ์ธ ๋‚ ์งœ๋ฅผ ์ฐพ๋Š” CTE
WITH first_logins AS (
    SELECT player_id, MIN(event_date) AS first_login  -- ๊ฐ ํ”Œ๋ ˆ์ด์–ด์˜ ์ฒซ ๋กœ๊ทธ์ธ ๋‚ ์งœ๋ฅผ ๊ฐ€์ ธ์˜ด
    FROM Activity
    GROUP BY player_id
),

-- ์ฒซ ๋กœ๊ทธ์ธ ๋‹ค์Œ๋‚  ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•œ ํ”Œ๋ ˆ์ด์–ด๋ฅผ ์ฐพ๋Š” CTE
next_day_logins AS (
    SELECT A.player_id  -- ์ฒซ ๋กœ๊ทธ์ธ ๋‹ค์Œ๋‚  ์ ‘์†ํ•œ ํ”Œ๋ ˆ์ด์–ด ID ๊ฐ€์ ธ์˜ด
    FROM first_logins A
    JOIN Activity B 
    ON A.player_id = B.player_id 
    AND B.event_date = A.first_login + INTERVAL '1 DAY'  -- ์ฒซ ๋กœ๊ทธ์ธ ๋‹ค์Œ๋‚  ์ ‘์†ํ•œ ๊ฒฝ์šฐ๋งŒ ์„ ํƒ
)

-- ์ฒซ ๋กœ๊ทธ์ธ ๋‹ค์Œ๋‚  ๋‹ค์‹œ ์ ‘์†ํ•œ ํ”Œ๋ ˆ์ด์–ด ๋น„์œจ ๊ณ„์‚ฐ
SELECT ROUND(COUNT(next_day_logins.player_id) * 1.0 / COUNT(first_logins.player_id), 2) AS fraction
FROM first_logins
LEFT JOIN next_day_logins 
ON first_logins.player_id = next_day_logins.player_id;

 

 

ํ’€์ด ๋ฐฉ์‹

  1. ์ฒซ ๋กœ๊ทธ์ธ ๋‚ ์งœ ์ฐพ๊ธฐ (CTE : first_logins)
    • player_id ๋ณ„๋กœ ๊ฐ€์žฅ ๋น ๋ฅธ ๋กœ๊ทธ์ธ ๋‚ ์งœ(MIN(event_date))๋ฅผ ์ฐพ๋Š”๋‹ค.
    • player_id์— ๋Œ€ํ•ด ์ฒซ ๋กœ๊ทธ์ธ ๋‚ ์งœ(first_login)์„ ๊ฐ–๋Š” ์ž„์‹œ ํ…Œ์ด๋ธ”์ด ์ƒ์„ฑ๋œ๋‹ค.
  2. ๋‹ค์Œ๋‚  ๋กœ๊ทธ์ธํ•œ ์œ ์ € ์ฐพ๊ธฐ (CTE : next_day_logins)
    • first_logins์™€ Activity๋ฅผ player_id ๊ธฐ์ค€์œผ๋กœ JOIN ํ•œ๋‹ค.
    • Activity ํ…Œ์ด๋ธ”์—์„œ ์œ ์ €์˜ ๋กœ๊ทธ์ธ ๋‚ ์งœ๊ฐ€ ์ฒซ ๋กœ๊ทธ์ธ ๋‹ค์Œ๋‚ (first_login + 1์ผ)์ธ ๊ฒฝ์šฐ๋ฅผ ์ฐพ๋Š”๋‹ค.
    • ๋‹ค์Œ๋‚  ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•œ player_id ๋ชฉ๋ก์„ ์–ป๋Š”๋‹ค.
  3. ๋‹ค์Œ๋‚  ๋กœ๊ทธ์ธํ•œ ์œ ์ €์˜ ๋น„์œจ ๊ณ„์‚ฐ
    • first_logins์™€ next_day_logins๋ฅผ player_id ๊ธฐ์ค€์œผ๋กœ LEFT JOIN ํ•œ๋‹ค.
    • (1) ์ฒซ ๋กœ๊ทธ์ธ ๋‹ค์Œ๋‚  ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•œ ์œ ์ € ์ˆ˜ : COUNT(next_day_logins.player_id)
    • (2) ์ „์ฒด ์œ ์ € ์ˆ˜ : COUNT(first_logins.player_id)
    • (1) / (2) ๋กœ ๋น„์œจ ๊ณ„์‚ฐํ•œ ํ›„, ROUND๋กœ ์†Œ์ˆ˜์  ๋‘˜์งธ ์ž๋ฆฌ๊นŒ์ง€ ๋ฐ˜์˜ฌ๋ฆผํ•œ๋‹ค.

 

 

ROUND

์†Œ์ˆ˜์  ๋‘˜์งธ ์ž๋ฆฌ๊นŒ์ง€ ๋ฐ˜์˜ฌ๋ฆผ(ROUND(..., 2)) ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค.

https://youngone-kang.tistory.com/51

 

[SQL] ROUND, CEIL, FLOOR (๋ฐ˜์˜ฌ๋ฆผ, ์˜ฌ๋ฆผ, ๋‚ด๋ฆผ)

โ  ROUND()  →  ๋ฐ˜์˜ฌ๋ฆผโ  CEIL()        →  ์˜ฌ๋ฆผโ  FLOOR()   →  ๋‚ด๋ฆผ   ๐Ÿ“Œ ROUND (๋ฐ˜์˜ฌ๋ฆผ)ROUND() ํ•จ์ˆ˜๋Š” ์ˆซ์ž๋ฅผ ๋ฐ˜์˜ฌ๋ฆผํ•˜์—ฌ ์ง€์ •ํ•œ ์ž๋ฆฟ์ˆ˜๊นŒ์ง€ ํ‘œํ˜„ํ•˜๋Š” ํ•จ์ˆ˜๊ธฐ๋ณธROUND(number, decimal_places)numb

youngone-kang.tistory.com

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90