๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

SQL

[SQL] MySQL๋กœ ์ค‘์•™๊ฐ’(Median) ์ฐพ์•„๋‚ด๊ธฐ - (HackerRank - Weather Observation Station 20 ๋ฌธ์ œ)

๋ฐ˜์‘ํ˜•

๐Ÿ”Š ๋ณธ ํฌ์ŠคํŒ…์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ…Œ์ด๋ธ”์˜ ์ž๋ฃŒ์™€ ์ถœ์ฒ˜๋Š” HackerRank ์ž„์„ ๋ฐํž™๋‹ˆ๋‹ค. ๋” ๋‹ค์–‘ํ•œ SQL ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด์‹œ๋ ค๋ฉดHackerRank ์‚ฌ์ดํŠธ๋ฅผ ๋ฐฉ๋ฌธํ•ด ๋ณด์„ธ์š”!

 

HackerRank ์‚ฌ์ดํŠธ

 

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” MySQL์„ ํ™œ์šฉํ•ด Median๊ฐ’์„ ์ถœ๋ ฅํ•ด๋ณด๋Š” ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด๋ ค ํ•œ๋‹ค. Median์ด๋ž€, ์ž˜ ์•Œ๋‹ค์‹œํ”ผ ์ค‘์•™๊ฐ’์„ ์˜๋ฏธํ•˜๋ฉฐ ๋ณดํ†ต ๋ฐ์ดํ„ฐ ๋ถ„ํฌ๊ฐ€ ์น˜์šฐ์ณ์ ธ ์žˆ์„ ๋•Œ ๋ฐ์ดํ„ฐ์˜ ๋Œ€ํ‘ฏ๊ฐ’์œผ๋กœ ์ž์ฃผ ์„ค์ •ํ•˜๋Š” ์ฒ™๋„์ด๋‹ค. ์ด๋Ÿฐ ์ค‘์•™๊ฐ’์„ SQL๋กœ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž. ๋ฌธ์ œ์˜ ์›๋ณธ์€ ์—ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์ž. ๋ฌธ์ œ์˜ ์š”๊ตฌ์‚ฌํ•ญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

A median is defined as a number separating the higher half of a data set from the lower half. Query themedianof theNorthern Latitudes(LAT_N) fromSTATIONand round your answer to 4 decimal places.
(STATION์ด๋ผ๋Š” ํ…Œ์ด๋ธ”์˜ LAT_N ์นผ๋Ÿผ์˜ ์ค‘์•™๊ฐ’์„ ์ถœ๋ ฅํ•˜๋ผ. ์ด ๋•Œ ์ถœ๋ ฅ๊ฐ’์„ ์†Œ์ˆ˜์  5๋ฒˆ์งธ ์ž๋ฆฌ์—์„œ ๋ฐ˜์˜ฌ๋ฆผํ•˜์—ฌ ์†Œ์ˆ˜ 4๋ฒˆ์žฌ ์ž๋ฆฌ๊นŒ์ง€ ์ถœ๋ ฅ์‹œ์ผœ๋ผ.)

ํ…Œ์ด๋ธ” ํ˜•ํƒœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

์ฃผ์–ด์ง„ ํ…Œ์ด๋ธ” STATION์˜ ์Šคํ‚ค๋งˆ

 

SQL์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ์ง‘๊ณ„ํ•จ์ˆ˜๋กœ๋Š” MAX(์ตœ๋Œ“๊ฐ’), MIN(์ตœ์†Ÿ๊ฐ’), AVG(ํ‰๊ท ๊ฐ’) ๋“ฑ์ด ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฌธ์ œ๋ฅผ ์ฒ˜์Œ ํ’€ ๋‹น์‹œ MEDIAN() ์ด๋ผ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์„๊นŒ? ์‹ถ์–ด์„œ ๊ตฌ๊ธ€๋ง์„ ํ•ด๋ณด๋‹ˆ ์—ญ์‹œ๋‚˜ ์—†์—ˆ๋‹ค..

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ์ค‘์•™๊ฐ’์„ ์ถœ๋ ฅํ•˜๋„๋ก ํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ ๋ฌธ์ œ ํ•ด๊ฒฐ ์•„์ด๋””์–ด๋ฅผ ๋– ์˜ฌ๋ฆด ๋•Œ ์ €๋ฒˆ์— ํ’€์–ด๋ณด์•˜๋˜ ๋ฌธ์ œ์—์„œ ํžŒํŠธ๋ฅผ ์–ป์—ˆ๋‹ค. ๋ฐ”๋กœ SET์ด๋ผ๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ด์šฉํ•ด ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•ด์ฃผ๊ณ  ์ด๋ฅผ ์ด์šฉํ•ด ํ…Œ์ด๋ธ” ํ–‰(Row)์˜ index๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํŒŒ์ƒ ์นผ๋Ÿผ์„ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ! ์šฐ์„  ์ •๋‹ต SQL ๊ตฌ๋ฌธ์„ ์‚ดํŽด๋ณด์ž.

 

SET @rowIndex=-1;
SELECT ROUND(AVG(lat_n), 4) AS Median
FROM (SELECT @rowIndex:=@rowIndex+1 AS RowNumber,
                lat_n
      FROM station
      ORDER BY lat_n) sub
WHERE RowNumber IN (FLOOR(@rowIndex / 2), CEIL(@rowIndex / 2))

 

์ž, ์ด์ œ ์ •๋‹ต SQL ๊ตฌ๋ฌธ์„ ํ•˜๋‚˜์”ฉ ๋œฏ์–ด๋ณด์ž. ์šฐ์„ , ์ค‘์•™๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ •๋ ฌํ–ˆ์„ ๋•Œ, ๊ฐ€์šด๋ฐ ์ˆœ๋ฒˆ์— ์žˆ๋Š” ์ˆซ์ž๋ฅผ ์ค‘์•™๊ฐ’์ด๋ผ๊ณ  ํ•œ๋‹ค.(์ด ๋•Œ, ์ •๋ ฌ๊ธฐ์ค€์€ ์˜ค๋ฆ„์ฐจ์ˆœ์ด๋˜ ๋‚ด๋ฆผ์ฐจ์ˆœ์ด๋˜ ์ƒ๊ด€์—†์Œ) ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— SET์„ ํ™œ์šฉํ•ด ํ…Œ์ด๋ธ” ํ–‰์˜ ์ˆซ์ž๋ฅผ ์„ธ์ฃผ์ž. ์ด ๋•Œ -1์ด๋ผ๊ณ  ์„ค์ •ํ•˜๋Š” ์ด์œ ๋Š” ์ดํ›„์— ์ค‘์•™๊ฐ’์„ ์ฐพ์„ ๋•Œ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๊ฐ€ ํ™€์ˆ˜/์ง์ˆ˜์— ๋”ฐ๋ผ ์„ค์ • ๋ฐฉ๋ฒ•์ด ๋‹ฌ๋ผ์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.(์ด ๋ถ€๋ถ„์€ ํ•˜๋‹จ์—์„œ ์‚ดํŽด๋ณด์ž.)

 

SET @rowIndex=-1;
SELECT @rowIndex:=@rowIndex+1,
       lat_n
FROM station
ORDER BY lat_n

 

์œ„ SQL๊ตฌ๋ฌธ์œผ๋กœ ์šฐ์„  LAT_N๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ–ˆ์„ ๋•Œ ํ…Œ์ด๋ธ”์˜ ํ–‰ ์ˆซ์ž๋ฅผ ๋งค๊ธฐ๊ณ  LAT_N ๊ฐ’์„ ์ถœ๋ ฅํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์•„์ง„๋‹ค.

 

๊ฒฐ๊ณผํ™”๋ฉด

 

์ด์ œ ์œ„ ๊ฒฐ๊ณผ์—์„œ ์ค‘์•™๊ฐ’์„ ์ฐพ์•„์ฃผ๋ฉด ๋˜๋Š”๋ฐ, ์ •๋‹ต SQL ๊ตฌ๋ฌธ์˜ WHERE ์ ˆ์ด ํ•œ ๋ฒˆ์— ์ดํ•ด๊ฐ€ ํ™• ์™€๋‹ฟ์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ ์˜ˆ์‹œ๋ฅผ ํ•œ ๋ฒˆ๋“ค์–ด๋ณด์ž. ํ–‰์˜ ์ฒซ ๋ฒˆ์งธ Index๋Š” 0์œผ๋กœ ์„ค์ •ํ–ˆ์„ ๋•Œ์ด๋‹ค. ์šฐ์„  ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๊ฐ€ ์ง์ˆ˜๊ฐœ์ผ ๋•Œ์ด๋‹ค.

 

RowNumber Value
0 100
1 200
2 300
3 400

 

์œ„์—์„œ ์ค‘์•™๊ฐ’์€ RowNumber๊ฐ€ 1๊ณผ 2์ผ ๋•Œ์˜ Value๋ฅผ ํ‰๊ท ๋‚ธ ๊ฐ’์ธ 250์ด ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ๋งˆ์ง€๋ง‰ RowNumber์ธ 3์„ 2๋กœ ๋‚˜๋ˆ„๊ฒŒ ๋˜๋ฉด 1.5๊ฐ€ ๋˜๊ณ  ์ด๋ฅผ FLOOR(๋‚ด๋ฆผ ์ฒ˜๋ฆฌ)ํ•˜๋ฉด 1, CEIL(์˜ฌ๋ฆผ ์ฒ˜๋ฆฌ)ํ•˜๋ฉด 2๊ฐ€ ๋˜๊ฒŒ ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์˜ฌ๋ฆผ, ๋‚ด๋ฆผ์ฒ˜๋ฆฌํ•œ ๊ฐ๊ฐ์˜ RowNumber์— ํ•ด๋‹นํ•˜๋Š” Value 2๊ฐœ๋ฅผ ํ‰๊ท ๊ฐ’์„ ๋‚ด๊ฒŒ ๋˜๋ฉด ์ค‘์•™๊ฐ’์ด ๋œ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋ฐ˜๋Œ€๋กœ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๊ฐ€ ํ™€์ˆ˜์ผ ๋•Œ๋ฅผ ์‚ดํŽด๋ณด์ž.

 

RowNumber Value
0 100
1 200
2 300
3 400
4 500

 

์œ„์—์„œ ์ค‘์•™๊ฐ’์€ 300์ด ๋œ๋‹ค. ๋งˆ์ง€๋ง‰ RowNumber์ธ 4๋ฅผ 2๋กœ ๋‚˜๋ˆ„๊ฒŒ ๋˜๋ฉด 2๋กœ ๋‚˜๋ˆ„์–ด๋–จ์–ด์ง„๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์–ด์ฐจํ”ผ ์ •์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ FLOOR, CEIL ์ฒ˜๋ฆฌ ํ•˜์—ฌ๋„ ๋™์ผํ•˜๊ฒŒ ์ •์ˆ˜์ธ 2๊ฐ€ ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค. ๋˜ํ•œ RowNumber = 2์ธ Value์ธ 300 2๊ฐœ์˜ ๊ฐ’์„ ํ‰๊ท ๊ฐ’์„ ๋‚ด์–ด๋„ ๋™์ผํ•˜๊ฒŒ 300์ด ๋œ๋‹ค.

 

๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜์— ์ƒ๊ด€์—†์ด ์ฒซ ๋ฐ์ดํ„ฐ ํ–‰์˜ Index๊ฐ€ 0์œผ๋กœ ์‹œ์ž‘ํ•  ๋•Œ, ๋งˆ์ง€๋ง‰ ํ–‰ Index๋ฅผ ๊ฐ€์ง€๊ณ  ์ค‘์•™๊ฐ’์„ ๊ณ„์‚ฐํ•ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ํ•„์ž์˜ ์„ค๋ช…์œผ๋กœ๋„ ์ดํ•ด๊ฐ€ ์ž˜ ๊ฐ€์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ผญ ๋…ธํŠธ์— ํ•„๊ธฐํ•ด์„œ๋ผ๋„ ์ดํ•ดํ•˜์ž! ๋จธ๋ฆฟ์†์œผ๋กœ ์ƒ๊ฐ๋งŒ ํ•˜๋Š” ๊ฒƒ๊ณผ ์†์œผ๋กœ ์จ๋ณด์•„์„œ ์‹œ๊ฐ์œผ๋กœ ํ™•์ธํ•˜๋Š” ๊ฒƒ์€ ๋ถ„๋ช… ๋‹ค๋ฅด๋‹ค!

 

๊ฒฐ๊ตญ ์œ„์™€ ๊ฐ™์€ ๊ณผ์ •๋“ค์„ ๊ฑฐ์ณ ์ด์ „์— ๋ณด์—ฌ์ฃผ์—ˆ๋˜ ์ •๋‹ต SQL ๊ตฌ๋ฌธ์ด ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์€ WHERE ๊ตฌ๋ฌธ์— ๋งˆ์ง€๋ง‰ ํ–‰ Index๋ฅผ ์ •์˜ํ•ด์ค„ ๋•Œ RowNumber์ด ์•„๋‹Œ @rowIndex์ธ ์ด์œ ๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ ๊ตฌ๋ฌธ์—์„œ @rowIndex := @rowIndex+1 ๋กœ ๊ณ„์†์ ์œผ๋กœ ๋”ํ•ด์ฃผ์—ˆ๊ณ  ๊ฒฐ๊ตญ ๋งˆ์ง€๋ง‰์— ์ตœ์ข…์ ์œผ๋กœ ํ• ๋‹น๋œ @rowIndex ๋ณ€์ˆ˜์—๋Š” ๋งˆ์ง€๋ง‰ ํ–‰์˜ Index๊ฐ€ ๋‹ด๊ฒจ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

SET @rowIndex=-1;
SELECT ROUND(AVG(lat_n), 4) AS Median
FROM (SELECT @rowIndex:=@rowIndex+1 AS RowNumber,
                lat_n
      FROM station
      ORDER BY lat_n) sub
WHERE RowNumber IN (FLOOR(@rowIndex / 2), CEIL(@rowIndex / 2))

 

[์ฐธ์กฐ]

GeeksforGeeks - Calculate Median in MySQL

๋ฐ˜์‘ํ˜•