๐Ÿ“

10. SubQuery

ย 

10.1. ์„œ๋ธŒ์ฟผ๋ฆฌ

10.1.1. ์„œ๋ธŒ์ฟผ๋ฆฌ ๊ฐœ์š”

์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์ฟผ๋ฆฌ ๋‚ด์˜ ๋‹ค๋ฅธ ์ฟผ๋ฆฌ๋กœ ๋ฉ”์ธ์ฟผ๋ฆฌ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„ํ„ฐ๋ง, ๋ณ€ํ™˜ ๋˜๋Š” ์ง‘๊ณ„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
1๊ฐœ์˜ SQL๋ฌธ ๋‚ด์— ํฌํ•จ๋œ SELECT๋ฌธ์„ ์˜๋ฏธํ•˜๋ฉฐ, ์„œ๋ธŒ์ฟผ๋ฆฌ ๋ฐ–์— ์žˆ๋Š” SQL๋ฌธ์„ ๋ฉ”์ธ์ฟผ๋ฆฌ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์†Œ๊ด„ํ˜ธ ์•ˆ์— ์ž‘์„ฑ๋˜๋ฉฐ, ๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ๋‹จ๋…์œผ๋กœ ์‹คํ–‰๋  ์ˆ˜ ์—†์œผ๋ฉฐ, ํ•ญ์ƒ ๋ฉ”์ธ์ฟผ๋ฆฌ์™€ ์—ฐ๊ณ„๋˜์–ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
ย 
๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํšจ๊ณผ์ ์ธ ๋„๊ตฌ๋กœ์„œ, ๋‘ ๊ฐœ ์ด์ƒ์˜ ํ…Œ์ด๋ธ”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•  ๋•Œ๋‚˜ ๋ณต์žกํ•œ SQL ๋ฌธ์„ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
notion imagenotion image
๐Ÿ’ก
JOIN์œผ๋กœ ์ž‘์„ฑ๋œ SQL ๋ฌธ์€ ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ํฌํ•จ๋œ SQL ๋ฌธ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. JOIN๋„ ์„œ๋ธŒ์ฟผ๋ฆฌ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋‘ ๊ฐœ ์ด์ƒ์˜ ํ…Œ์ด๋ธ”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ์‚ฌ์šฉํ•˜์ง€๋งŒ, 2๊ฐœ์˜ ํ…Œ์ด๋ธ”์—์„œ 1๊ฐœ์˜ ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ณ ์ž ํ•  ๋•Œ๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๊ณ  3๊ฐœ ์ด์ƒ์˜ ํ…Œ์ด๋ธ”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” JOIN์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
3๊ฐœ ์ด์ƒ์˜ ํ…Œ์ด๋ธ”์—์„œ๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ ๋Œ€์‹  JOIN์„ ์‚ฌ์šฉํ•  ์‹œ ์ฟผ๋ฆฌ๊ฐ€ ๋” ๊ฐ„๊ฒฐํ•ด์ง€๊ณ  ๊ฐ€๋…์„ฑ์ด ๋†’์•„์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
ย 
์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” SELECT, FROM, WHERE, HAVING ๋ฐ JOIN ์ ˆ ๋“ฑ ๋‹ค์–‘ํ•œ SQL ์ ˆ์—์„œ ํ™œ์šฉ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฉ”์ธ์ฟผ๋ฆฌ๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋˜๋Š” ์ข…์†์ ์ธ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์†Œ๊ด„ํ˜ธ ๋‚ด์— ์ •์˜๋˜๋ฉฐ, ๋‹จ์ผ ๊ฐ’ ๋˜๋Š” ์ง‘ํ•ฉ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ, ๋‹ค์–‘ํ•œ ๋น„๊ต ์—ฐ์‚ฐ์ž(=, <, >, IN, NOT IN, EXIST, NOT EXIST ๋“ฑ)์™€ ๊ฒฐํ•ฉํ•˜์—ฌ ๋ณต์žกํ•œ ์กฐ๊ฑด์„ ํ‘œํ˜„ํ•˜๋Š” ๋ฐ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก
์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ์ข…๋ฅ˜๋‚˜ ๋ชฉ์ ์— ๋”ฐ๋ผ์„œ ORDER BY์ ˆ์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์กฐ๊ฑด์ ˆ ์„œ๋ธŒ์ฟผ๋ฆฌ(IN, EXISTS ๋“ฑ)๋Š” ๊ฒฐ๊ณผ ์ง‘ํ•ฉ์˜ ์กด์žฌ๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ๊ตฌ๋ฌธ ์•ˆ์—์„œ๋Š” ORDER BY์ ˆ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
ย 

10.1.2. ์‚ฌ์šฉ ๋ชฉ์ 

์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์•Œ๋ ค์ง€์ง€ ์•Š์€ ๊ธฐ์ค€์œผ๋กœ ๊ฒ€์ƒ‰ํ•  ๋•Œ ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์ด๋ธ” ๋‚ด์—์„œ ์กฐ๊ฑด์„ ์„ค์ •ํ•˜๊ธฐ ์–ด๋ ค์›Œ ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์—์„œ ์กฐ๊ฑด์„ ๊ฐ€์ ธ์™€์•ผ ํ•  ๊ฒฝ์šฐ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ํŠน์ • ๊ธฐ์ค€๊ฐ’์„ ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•˜๊ณ , ๊ทธ ๊ฐ’์„ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ค๋ฅธ ์ฟผ๋ฆฌ์—์„œ ํ™œ์šฉํ•˜๋Š” ์ƒํ™ฉ์—์„œ ํฐ ์žฅ์ ์„ ๋ฐœํœ˜ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์•„๋ž˜์™€ ๊ฐ™์ด ์—ด ๋ฐ์ดํ„ฐ ์ƒ์„ฑ, ์ž„์‹œ ํ…Œ์ด๋ธ” ์ƒ์„ฑ, ์ง‘ํ•ฉ ์—ฐ์‚ฐ ์ˆ˜ํ–‰, ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ, ๋ณต์žกํ•œ ์งˆ์˜์ฒ˜๋ฆฌ ์‹œ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
์กฐ๊ฑด ์ œ๊ณต: ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” WHERE๋‚˜ HAVING ์ ˆ์—์„œ ์กฐ๊ฑด๊ฐ’์„ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํŠน์ • ํ‰๊ท ๊ฐ’ ์ด์ƒ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ, ๊ทธ ํ‰๊ท ๊ฐ’์„ ๊ตฌํ•˜๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์—ด ๋ฐ์ดํ„ฐ ์ƒ์„ฑ: SELECT ์ ˆ์—์„œ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„์ถœ๋œ ์—ด ๊ฐ’์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ž„์‹œ ํ…Œ์ด๋ธ” ์ƒ์„ฑ: FROM ์ ˆ์—์„œ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž„์‹œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๊ณ , ์ด ํ…Œ์ด๋ธ”์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฉ”์ธ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ง‘ํ•ฉ ์—ฐ์‚ฐ ์ˆ˜ํ–‰: ์—ฌ๋Ÿฌ ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋ฅผ UNION, INTERSECT, EXCEPT ๋“ฑ์˜ ์—ฐ์‚ฐ์ž๋กœ ๊ฒฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ฐ์ดํ„ฐ ๊ฒ€์ฆ: ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๊ฐ€ ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ฑฐ๋‚˜, ํŠน์ • ๊ฐ’์„ ๊ฐ€์ง€๋Š”์ง€ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ณต์žกํ•œ ์งˆ์˜ ์ฒ˜๋ฆฌ: ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋‹จ์ˆœํ™”ํ•˜์—ฌ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๋‹จ๊ณ„์˜ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์ค‘์ฒฉํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 

10.1.3. ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ํšจ์œจ์„ฑ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ฟผ๋ฆฌ์˜ ์‹คํ–‰ ์‹œ๊ฐ„์€ ๋งค์šฐ ์ค‘์š”ํ•œ ์ง€ํ‘œ์ž…๋‹ˆ๋‹ค. ํŠนํžˆ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ, ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๋น„ํšจ์œจ์ ์ธ ์‚ฌ์šฉ์€ ์‹คํ–‰ ์‹œ๊ฐ„์˜ ํฐ ์ง€์—ฐ์„ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํ•ญ์ƒ ํšจ์œจ์„ฑ์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
ย 
์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ฝ”๋“œ ์žฌ์‚ฌ์šฉ: ๊ฐ™์€ ๋กœ์ง์ด๋‚˜ ์กฐ๊ฑด์„ ์—ฌ๋Ÿฌ ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ, ๊ทธ ๋กœ์ง์„ ์„œ๋ธŒ์ฟผ๋ฆฌ๋กœ ๋งŒ๋“ค์–ด ์žฌ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ช…์‹œ์ ์ธ ์ˆœ์„œ : ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉ ์‹œ, ์—ฐ์‚ฐ ์ˆœ์„œ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ž„์‹œ ๊ฒฐ๊ณผ ์ƒ์„ฑ : ํŠน์ • ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•˜๋Š” ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ ์ง‘ํ•ฉ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ฉ”์ธ ์ฟผ๋ฆฌ์—์„œ ์—ฐ์‚ฐ์„ ์œ„ํ•œ ์ž„์‹œ๊ฒฐ๊ณผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ณ„์ธต์  ์งˆ์˜ : ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๊ณ„์ธต์ ์œผ๋กœ ํ‘œํ˜„ํ•˜๊ณ  ์งˆ์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์กฐ์ง ๋‚ด์˜ ์ƒํ•˜ ๊ด€๊ณ„๋‚˜ ๊ฐ€๊ณ„๋„์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ ์‚ฌ์ด์˜ ๊ณ„์ธต์  ๊ด€๊ณ„๋ฅผ ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•˜๊ณ  ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ณต์žก์„ฑ ๊ฐ์†Œ: ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๋ฉ”์ธ ์ฟผ๋ฆฌ์˜ ๊ฐ€๋…์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก
ํšจ์œจ์„ฑ๊ณผ ๊ด€๋ จ๋œ ์ฃผ์˜ ์‚ฌํ•ญ
  1. ๋„ˆ๋ฌด ๋งŽ์€ ์ค‘์ฒฉ๋œ ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์ฟผ๋ฆฌ์˜ ์„ฑ๋Šฅ์„ ์ €ํ•˜์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ์กฐ์ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ์ˆ˜๋ฅผ ์ตœ์†Œํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
  1. ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ, ์ด๋Š” ๋ฉ”์ธ ์ฟผ๋ฆฌ์˜ ์„ฑ๋Šฅ์— ๋ถ€์ •์ ์ธ ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ๋ฐ์ดํ„ฐ์˜ ์–‘์„ ์ตœ์†Œํ™”ํ•˜๋ ค๋ฉด ํ•„ํ„ฐ๋ง ์กฐ๊ฑด์„ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  1. ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ์กฐํšŒ๋˜๋Š” ์—ด์— ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ํ™œ์šฉ ์‹œ ์—ฐ์‚ฐ ๋น„์šฉ์ด ์ถ”๊ฐ€, ์ตœ์ ํ™”๋ฅผ ๋ฐ›์„ ์ˆ˜ ์—†์–ด ์ฟผ๋ฆฌ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ SQL ๋ฌธ์—์„œ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉ ์‹œ, ๋ถˆํ•„์š”ํ•œ JOIN์—ฐ์‚ฐํ•˜์ง€๋Š” ์•Š์•˜๋Š”์ง€, ํ…Œ์ด๋ธ” ์ ‘๊ทผ์„ ์ตœ์†Œํ™”ํ–ˆ๋Š”์ง€ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋ณต์žกํ•œ ์ฟผ๋ฆฌ์—์„œ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋™์ผํ•œ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ๋™์ผํ•œ ์—ฐ์‚ฐ์ด ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰๋˜์–ด ํšจ์œจ์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ WITH์ ˆ์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ค๋ฉฐ, ๋™์ผํ•œ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜์—ฌ ํšจ์œจ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 

10.1.4. WITH

WITH ์ ˆ์€ ์ฟผ๋ฆฌ์˜ ์‹œ์ž‘ ๋ถ€๋ถ„์—์„œ ์ •์˜๋˜๋ฉฐ, ์ดํ›„์˜ ์ฃผ ์ฟผ๋ฆฌ์—์„œ ์—ฌ๋Ÿฌ ๋ฒˆ ์ฐธ์กฐ๋  ์ˆ˜ ์žˆ๋Š” ์ผ์‹œ์ ์ธ ๊ฒฐ๊ณผ ์ง‘ํ•ฉ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ํ•„์š”ํ•œ ์ปฌ๋Ÿผ๋งŒ ์ถ”์ถœํ•ด ์ž„์‹œ ํ…Œ์ด๋ธ”๋ช…์„ ์ •์˜ํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ๊ณ„์‚ฐ ๋˜๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
WITH์ ˆ์€ โ€˜๊ฐ€๋…์„ฑโ€™, โ€˜์žฌ์‚ฌ์šฉ์„ฑโ€™, โ€˜๋กœ์ง์˜ ์ˆœ์ฐจ์  ํ‘œํ˜„โ€™, โ€˜ํšจ์œจ์„ฑโ€™ ์ด๋ผ๋Š” ํŠน์ง•์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋ถ„ํ•ดํ•˜๊ณ , ์ค‘๊ฐ„ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜์—ฌ ์ฟผ๋ฆฌ์˜ ๊ฐ€๋…์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ณ  ๊ตฌ์กฐํ™”ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค
  1. ๊ฐ€๋…์„ฑ: ๋ณต์žกํ•œ ์ฟผ๋ฆฌ์˜ ๊ตฌ์กฐ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ ๋ถ€๋ถ„์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  1. ์žฌ์‚ฌ์šฉ์„ฑ: ๋™์ผํ•œ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์žฌ์‚ฌ์šฉํ•  ํ•„์š” ์—†์ด ํ•œ ๋ฒˆ๋งŒ ์ •์˜ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
  1. ๋กœ์ง์˜ ์ˆœ์ฐจ์  ํ‘œํ˜„: WITH์ ˆ์„ ์—ฐ์‡„์ ์œผ๋กœ ์ •์˜ํ•˜๋ฉด, ์ฟผ๋ฆฌ์˜ ์‹คํ–‰ ๋กœ์ง์„ ๋‹จ๊ณ„๋ณ„๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํŠนํžˆ ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ ๋‹จ๊ณ„๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ํ‘œํ˜„ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  1. ํšจ์œจ์„ฑ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋”ฐ๋ผ, WITH์ ˆ์˜ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹ฑํ•˜์—ฌ ์ฃผ ์ฟผ๋ฆฌ์—์„œ์˜ ๋ฐ˜๋ณต๋œ ์ฐธ์กฐ์— ๋Œ€ํ•œ ์—ฐ์‚ฐ์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด WITH ์ ˆ ์•ˆ์— ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ์ž„์‹œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, ํ•˜๋‚˜์˜ ํ…Œ์ด๋ธ”๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ฝค๋งˆ(,)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋™์‹œ์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž„์‹œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์–ด CTE(Common Table Expressions)์ด๋ผ๊ณ ๋„ ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
WITH new_table1 AS ( SELECT column1 FROM Table1 ), new_table2 AS ( SELECT column1 FROM Table2 ) SELECT * FROM new_table1;
ย 
์ด์ „์—๋Š” ๋ณต์žกํ•œ ์ฟผ๋ฆฌ์˜ ๊ฒฝ์šฐ FROM์ ˆ ์•ˆ์— SELECT๊ฐ€ ๋“ค์–ด๊ฐ€๋„๋ก ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.
SELECT column1 FROM ( SELECT * FROM Table1 );
ย 
์ด๋•Œ, WITH ์ ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋…ผ๋ฆฌ์ ์œผ๋กœ ์„ธ๋ถ„ํ™”ํ•˜๊ณ  ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ž„์‹œ ํ…Œ์ด๋ธ”๋กœ ์ƒ์„ฑํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ๊ตฌ์กฐํ™”ํ•  ์ˆ˜ ์žˆ๊ณ  ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋” ์ž‘์€ ๋…ผ๋ฆฌ์  ๋ธ”๋ก์œผ๋กœ ๋‚˜๋ˆ„์–ด ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์œ ์ง€ ๋ณด์ˆ˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก
WITH์ ˆ์€ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜๋ฉด ๋งŽ์€ ์ด์ ์„ ์ œ๊ณตํ•˜์ง€๋งŒ, ๋‚จ๋ฐœํ•˜๋ฉด ๋ณต์žก์„ฑ๊ณผ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ WITH์ ˆ์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํ•ญ์ƒ ์„ฑ๋Šฅ๊ณผ ๊ฐ€๋…์„ฑ์˜ ๊ท ํ˜•์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
ย 
์˜ˆ์‹œ 1
โ€œemployeesโ€์˜ โ€œemployee_idโ€ ๊ฐ’์„ ์กฐํšŒํ•˜๋Š” โ€œemployee_dataโ€๋ผ๋Š” ์ž„์‹œ ํ…Œ์ด๋ธ”์„ ์ •์˜ํ•˜๊ณ  โ€œemployee_dataโ€ ํ…Œ์ด๋ธ”๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
WITH employee_data AS ( SELECT employee_id FROM `HR.employees` ) SELECT * FROM employee_data;
notion imagenotion image
ย 
์˜ˆ์‹œ 2
์ง์—…๋ณ„ ์ง์› ์•„์ด๋”” ์ˆ˜๋ฅผ โ€œemployee_job_countsโ€๋ผ๋Š” ์ž„์‹œ ํ…Œ์ด๋ธ”๋กœ ์ •์˜ํ•˜๊ณ  โ€œemployee_job_countsโ€ ํ…Œ์ด๋ธ”๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
WITH employee_job_counts AS ( SELECT job_id , COUNT(employee_id) AS job_count FROM `HR.employees` GROUP BY job_id ) SELECT * FROM employee_job_counts ORDER BY job_count DESC;
notion imagenotion image
ย 
์˜ˆ์‹œ 3
์ง์ข…๋ณ„ ์ง์› ์ˆ˜๊ฐ€ 20 ์ด์ƒ์ธ ์ง์ข… ์ฝ”๋“œ(โ€job_codeโ€)์™€ ์ง์› ์ˆ˜๋ฅผ โ€œemployee_countsโ€๋ผ๋Š” ์ž„์‹œ ํ…Œ์ด๋ธ”์„ ์ •์˜ํ•˜๊ณ  โ€œemployee_countsโ€ ํ…Œ์ด๋ธ”๋กœ๋ถ€ํ„ฐ ์ง์ข…๋ณ„ ์ง์› ์ˆ˜๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
WITH employee_counts AS ( SELECT LEFT(job_id,2) AS job_code , COUNT(LEFT(job_id,2)) AS employee_count FROM `HR.employees` GROUP BY job_code HAVING COUNT(job_code)>=20 ) SELECT * FROM employee_counts;
notion imagenotion image
ย 
์˜ˆ์‹œ 4
๊ตญ๊ฐ€ ํ…Œ์ด๋ธ”๊ณผ ๋ถ€์„œ ํ…Œ์ด๋ธ”, ์ง์› ํ…Œ์ด๋ธ”์„ ์ด์šฉํ•˜์—ฌ ๊ตญ๊ฐ€๋ณ„ ๋ถ€์„œ์— ๊ทผ๋ฌดํ•˜๋Š” ์ง์› ์ˆ˜๋ฅผ ๊ตฌํ•ฉ๋‹ˆ๋‹ค.
WITH dep_loc_join AS ( SELECT d.department_id , d.department_name , l.country_id FROM `HR.departments` AS d LEFT JOIN `HR.locations` AS l ON d.location_id = l.location_id ), dep_loc_emp_join AS ( SELECT e.employee_id , e.department_id , dl.department_name , dl.country_id FROM `HR.employees` AS e LEFT JOIN dep_loc_join AS dl ON e.department_id = dl.department_id ) SELECT country_id , department_name , COUNT(employee_id) AS employee_count FROM dep_loc_emp_join GROUP BY country_id, department_name;
ย 
์˜ˆ์‹œ 4-1
๊ตญ๊ฐ€๋ณ„ ์–ด๋–ค ๋ถ€์„œ๋“ค์ด ์žˆ๋Š”์ง€ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•˜์—ฌ โ€œdepartmentsโ€ ํ…Œ์ด๋ธ”๊ณผ โ€œlocationsโ€ ํ…Œ์ด๋ธ”์„ LEFT JOIN ํ•˜์—ฌ โ€œdepartment_idโ€, โ€œdepartment_nameโ€, โ€œcountry_idโ€๋ฅผ ์กฐํšŒํ•˜๊ณ  โ€œdep_loc_joinโ€๋ผ๋Š” ์ž„์‹œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
WITH dep_loc_join AS ( SELECT d.department_id , d.department_name , l.country_id FROM `HR.departments` AS d LEFT JOIN `HR.locations` AS l ON d.location_id = l.location_id ) SELECT * FROM dep_loc_join;
notion imagenotion image
ย 
์˜ˆ์‹œ 4-2
๊ตญ๊ฐ€๋ณ„ ๋ถ€์„œ๋ณ„ ์ง์› ์ˆ˜๋ฅผ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด โ€œemployeesโ€ ํ…Œ์ด๋ธ”๊ณผ ์˜ˆ์‹œ 4-1์˜ โ€œdep_loc_joinโ€ ํ…Œ์ด๋ธ”์„ LEFT JOIN ํ•˜์—ฌ โ€œemployee_idโ€, โ€œdepartment_idโ€, โ€œdepartment_nameโ€, โ€œcountry_idโ€๋ฅผ ์กฐํšŒํ•˜๊ณ  โ€œdep_loc_emp_joinโ€ ํ…Œ์ด๋ธ”๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
WITH dep_loc_join AS ( SELECT d.department_id , d.department_name , l.country_id FROM `HR.departments` AS d LEFT JOIN `HR.locations` AS l ON d.location_id = l.location_id ), dep_loc_emp_join AS ( SELECT e.employee_id , e.department_id , dl.department_name , dl.country_id FROM `HR.employees` AS e LEFT JOIN dep_loc_join AS dl ON e.department_id = dl.department_id ) SELECT * FROM dep_loc_emp_join;
notion imagenotion image
ย 
์˜ˆ์‹œ 4-3
์˜ˆ์‹œ 4-2์˜ โ€œdep_loc_emp_joinโ€ ํ…Œ์ด๋ธ”์„ ์ด์šฉํ•˜์—ฌ ๊ตญ๊ฐ€๋ณ„ ๋ถ€์„œ๋ณ„ ์ง์› ์ˆ˜๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, โ€œcountry_idโ€, โ€œdepartment_nameโ€๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฌถ์–ด์ค€ ํ›„ ์ง์› ์ˆ˜(โ€employee_countโ€)๋ฅผ ๊ตฌํ•ด์ค๋‹ˆ๋‹ค.
WITH dep_loc_join AS ( SELECT d.department_id , d.department_name , l.country_id FROM `HR.departments` AS d LEFT JOIN `HR.locations` AS l ON d.location_id = l.location_id ), dep_loc_emp_join AS ( SELECT e.employee_id , e.department_id , dl.department_name , dl.country_id FROM `HR.employees` AS e LEFT JOIN dep_loc_join AS dl ON e.department_id = dl.department_id ) SELECT country_id , department_name , COUNT(employee_id) AS employee_count FROM dep_loc_emp_join GROUP BY country_id, department_name;
notion imagenotion image
ย 
์˜ˆ์‹œ 5
โ€œemployeesโ€ ํ…Œ์ด๋ธ”์—์„œ โ€œdepartment_idโ€ ๋ณ„๋กœ โ€œsalaryโ€์˜ ๋ถ„์‚ฐ์„ ๊ณ„์‚ฐํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.
์ผ๋ฐ˜์ ์œผ๋กœ ๋ถ„์‚ฐ์„ ๊ณ„์‚ฐํ•  ๋•Œ๋Š” VARIANCE() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋ชจ์ง‘๋‹จ์˜ ๋ถ„์‚ฐ์„ ๊ตฌํ•˜๋ ค๋ฉด VAR_POP() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • VARIANCE() ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ โ€œdepartment_idโ€ ๋ณ„ โ€œsalaryโ€์˜ ๋ถ„์‚ฐ์„ ๊ตฌํ•˜๋Š” ์˜ˆ์ œ
    • SELECT DISTINCT department_id , ROUND(VARIANCE(salary), 2) AS salary_variance FROM `HR.employees` GROUP BY department_id ORDER BY department_id;
      notion imagenotion image
ย 
  • VAR_POP() ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ โ€œdepartment_idโ€ ๋ณ„ โ€œsalaryโ€์˜ ๋ถ„์‚ฐ์„ ๊ตฌํ•˜๋Š” ์˜ˆ์ œ
    • SELECT DISTINCT department_id , ROUND(VAR_POP(salary), 2) AS salary_variance FROM `HR.employees` GROUP BY department_id ORDER BY department_id;
      notion imagenotion image
ย 
๊ทธ๋Ÿฌ๋‚˜ ๋ถ„์‚ฐ์„ ๊ณ„์‚ฐํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ์œˆ๋„์šฐ ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ถ„์‚ฐ์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŽธ์ฐจ์˜ ์ œ๊ณฑ์˜ ํ‰๊ท ์ด ๋ถ„์‚ฐ์ž„์„ ๊ณ ๋ คํ•˜์—ฌ, ์šฐ์„  ํŽธ์ฐจ์˜ ํ•ฉ์ด 0์ž„์„ ํ™•์ธํ•œ ๋‹ค์Œ, ํŽธ์ฐจ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ถ„์‚ฐ์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. WITH๋ฌธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
  • WITH ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ
    • โ€œdepartment_idโ€ ๋ณ„ โ€œsalaryโ€์˜ ํŽธ์ฐจ์˜ ํ•ฉ์„ ๊ตฌํ•˜๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.
      • WITH employee_salary_dev AS ( SELECT employee_id , salary - AVG(salary) OVER() AS deviation FROM `HR.employees` ) SELECT ROUND(SUM(deviation), 2) AS deviations_sum FROM employee_salary_dev;
        notion imagenotion image
    • โ€œdepartment_idโ€ ๋ณ„ โ€œsalaryโ€์˜ ๋ถ„์‚ฐ์„ ๊ตฌํ•˜๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.
      • WITH employee_salary_dev AS ( SELECT department_id , salary - AVG(salary) OVER(PARTITION BY department_id) AS deviation , COUNT(salary) OVER(PARTITION BY department_id) AS n FROM `HR.employees` ) SELECT department_id , ROUND(SUM(CASE WHEN n = 1 THEN 0 ELSE (deviation * deviation) / (n - 1) END), 2) AS variance FROM employee_salary_dev GROUP BY department_id ORDER BY department_id;
        notion imagenotion image
ย 
  • WITH๋ฌธ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ
    • โ€œdepartment_idโ€ ๋ณ„ โ€œsalaryโ€์˜ ํŽธ์ฐจ์˜ ํ•ฉ์„ ๊ตฌํ•˜๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.
      • SELECT ROUND(SUM(dev), 2) AS deviations_sum FROM ( SELECT salary - AVG(salary) OVER() AS dev FROM `HR.employees` );
        notion imagenotion image
    • โ€œdepartment_idโ€ ๋ณ„ โ€œsalaryโ€์˜ ๋ถ„์‚ฐ์„ ๊ตฌํ•˜๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.
      • SELECT department_id , ROUND(SUM(CASE WHEN n = 1 THEN 0 ELSE (deviation * deviation) / (n - 1) END), 2) AS variance FROM ( SELECT department_id , salary - AVG(salary) OVER(PARTITION BY department_id) AS deviation , COUNT(salary) OVER(PARTITION BY department_id) AS n FROM `HR.employees` ) GROUP BY department_id ORDER BY department_id;
        notion imagenotion image
ย 

10.2. ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ์ข…๋ฅ˜

์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ์ข…๋ฅ˜๋กœ๋Š” ์Šค์นผ๋ผ ์„œ๋ธŒ์ฟผ๋ฆฌ, ํ–‰ ์„œ๋ธŒ์ฟผ๋ฆฌ, ์—ด ์„œ๋ธŒ์ฟผ๋ฆฌ, ํ…Œ์ด๋ธ” ์„œ๋ธŒ์ฟผ๋ฆฌ ์ด 4๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  1. ์Šค์นผ๋ผ ์„œ๋ธŒ์ฟผ๋ฆฌ (Scalar Subquery):
    1. ๊ฒฐ๊ณผ๋กœ ๋‹จ์ผ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ SELECT ๋ฌธ์˜ ์—ด ๊ฐ’ ๋˜๋Š” WHERE ์ ˆ์˜ ์กฐ๊ฑด ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ ๊ฐ ํ–‰์— ๋Œ€ํ•œ ๊ฐ’์€ ๊ณ„์‚ฐํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      SELECT column1 , ( SELECT sub_column FROM sub_table WHERE condition ) AS alias FROM Table1;
ย 
  1. ํ–‰ ์„œ๋ธŒ์ฟผ๋ฆฌ (Row Subquery):
    1. ๊ฒฐ๊ณผ๋กœ ํ•˜๋‚˜์˜ ํ–‰์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์—ด์˜ ๊ฐ’์„ ํฌํ•จํ•˜๋Š” ๋‹จ์ผ ํ–‰์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ ๋‹ค์ค‘ ์ปฌ๋Ÿผ์˜ ๋น„๊ต๋ฅผ ์œ„ํ•ด WHERE์ ˆ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      SELECT column1 , column2 FROM Table1 WHERE (column1, column2) = ( SELECT sub_column1 , sub_column2 FROM sub_table WHERE condition );
ย 
  1. ์—ด ์„œ๋ธŒ์ฟผ๋ฆฌ (Column Subquery):
    1. ๊ฒฐ๊ณผ๋กœ ์—ฌ๋Ÿฌ ๊ฐ’์„ ํฌํ•จํ•˜๋Š” ๋‹จ์ผ ์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. IN, NOT IN๋“ฑ์˜ ์—ฐ์‚ฐ์ž์™€ ํ•จ๊ป˜ WHERE์ ˆ์—์„œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      SELECT column1 , column2 FROM Table1 WHERE column1 IN ( SELECT sub_column FROM sub_table WHERE condition );
ย 
  1. ํ…Œ์ด๋ธ” ์„œ๋ธŒ์ฟผ๋ฆฌ (Table Subquery):
    1. ๊ฒฐ๊ณผ๋กœ ์—ฌ๋Ÿฌ ํ–‰๊ณผ ์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ FROM ์ ˆ์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, ์ž„์‹œ ํ…Œ์ด๋ธ”์ฒ˜๋Ÿผ ์ž‘๋™ํ•˜์—ฌ JOIN์—ฐ์‚ฐ์ด๋‚˜ ์ธ๋ผ์ธ ๋ทฐ๋กœ ์‚ฌ์šฉํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
      SELECT column1 , column2 FROM ( SELECT sub_column1 , sub_column2 FROM sub_table WHERE condition ) AS alias;
ย 

10.2.1. ์Šค์นผ๋ผ

์Šค์นผ๋ผ ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‹จ์ผ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์ฃผ๋กœ SELECT ์ ˆ์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, ๊ฒฐ๊ณผ์˜ ๊ฐ ํ–‰์— ๋Œ€ํ•ด ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋‹จ์ผ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์Šค์นผ๋ผ ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ๋ฉ”์ธ์ฟผ๋ฆฌ์™€ ํ•จ๊ป˜ ์‹คํ–‰๋˜๋ฉฐ, ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœ๋˜๋Š” ๊ฒฝ์šฐ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ์ดˆ๋ž˜ํ•  ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์Šค์นผ๋ผ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ๊ฐ„์ด ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ์–ด ๋Œ€์•ˆ์œผ๋กœ JOIN ํ˜น์€ WINDOW FUNCTION์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ธฐ๋ณธ ๊ตฌ๋ฌธ
SELECT column1 , column2 , ( SELECT single_value FROM sub_table WHERE conditions ) AS scalar_sub_column FROM main_table WHERE main_table_conditions;
์„ค๋ช…
  • main_table : ๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์ธํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค.
  • sub_table : ์Šค์นผ๋ผ ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค.
  • column1, column2 : ๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ ์„ ํƒํ•œ ์—ด์ž…๋‹ˆ๋‹ค.
  • conditions : ๋ฉ”์ธ์ฟผ๋ฆฌ ๋ฐ ์Šค์นผ๋ผ ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ์กฐ๊ฑด์„ ์ง€์ •ํ•˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.
  • scalar_sub_column : ์Šค์นผ๋ผ ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๋‹จ์ผ ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ์—ด์ž…๋‹ˆ๋‹ค.
ย 
์˜ˆ์‹œ 1
๊ฐ ์ง์›์˜ ๋ถ€์„œ๋ณ„ ์ตœ๊ณ  ๊ธ‰์—ฌ๋ฅผ ๊ณ„์‚ฐํ•˜๊ณ  โ€œmax_salary_for_departmentโ€ ์ปฌ๋Ÿผ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.
SELECT e.employee_id , e.department_id , e.first_name || ' ' || e.last_name AS full_name , e.salary , ( SELECT MAX(salary) FROM `HR.employees` as ms WHERE department_id = e.department_id ORDER BY e.salary DESC ) AS max_salary_for_department FROM `HR.employees` AS e ORDER BY department_id;
WITH ์ ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณตํ†ต ํ…Œ์ด๋ธ”์ธ โ€œMaxSalariesโ€ ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ๋ถ€์„œ๋ณ„ ์ตœ๊ณ  ๊ธ‰์—ฌ๋ฅผ ๊ณ„์‚ฐํ•œ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ์˜ ์ง์› ์ •๋ณด์™€ ๋ถ€์„œ๋ณ„ ์ตœ๊ณ  ๊ธ‰์—ฌ๋ฅผ ๊ฒฐํ•ฉํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. WITH ์ ˆ์— ์„ ์–ธํ•œ ๊ณตํ†ต ํ…Œ์ด๋ธ”์€ ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ด ์ฝ”๋“œ์˜ ์œ ์ง€ ๋ฐ ์ˆ˜์ •์„ ์šฉ์ดํ•˜๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
WITH MaxSalaries AS ( SELECT department_id , MAX(salary) AS max_salary FROM `HR.employees` GROUP BY department_id ) SELECT e.employee_id , e.department_id , e.first_name || ' ' || e.last_name AS full_name , e.salary , ms.max_salary AS max_salary_for_department FROM `HR.employees` AS e LEFT JOIN MaxSalaries AS ms ON e.department_id = ms.department_id ORDER BY e.department_id;
notion imagenotion image
ย 
์˜ˆ์‹œ 2
โ€œemployeesโ€ ํ…Œ์ด๋ธ”๊ณผ โ€jobsโ€ ํ…Œ์ด๋ธ”์„ ํ™œ์šฉํ•˜์—ฌ ์ง์›์˜ ์ง๋ฌด ๋ช…์„ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. ํŠน์ • ์ง์›์˜ โ€œemployee_idโ€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ์ง์›์˜ ์ง๋ฌด ์ด๋ฆ„์„ ์Šค์นผ๋ผ ๊ฐ’์œผ๋กœ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ธŒ์ฟผ๋ฆฌ์™€ WITH์ ˆ์„ ์‚ฌ์šฉํ•œ ์ฟผ๋ฆฌ ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
SELECT employee_id , first_name || ' ' || last_name AS full_name , ( SELECT job_title FROM `HR.jobs` AS j WHERE j.job_id = e.job_id ) AS job_title FROM `HR.employees` AS e WHERE 1=1 , employee_id = 102;
WITH EmployeeJob AS ( SELECT e.employee_id , e.first_name || ' ' || e.last_name AS full_name , j.job_title FROM `HR.employees` AS e JOIN `HR.jobs` AS j ON e.job_id = j.job_id ) SELECT employee_id , full_name , job_title FROM EmployeeJob WHERE 1=1 , employee_id = 102;
notion imagenotion image
ย 

10.2.2 ์ธ๋ผ์ธ ๋ทฐ

์ธ๋ผ์ธ ๋ทฐ๋Š” FROM์ ˆ ๋‚ด์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ธ๋ผ์ธ ๋ทฐ๋Š” ์ฟผ๋ฆฌ ๋‚ด์—์„œ ์ž„์‹œ ํ…Œ์ด๋ธ”๋กœ ์ž‘๋™ํ•˜๋ฉฐ, ์ฃผ ์ฟผ๋ฆฌ์—์„œ ํ•ด๋‹น ๊ฒฐ๊ณผ๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ธ๋ผ์ธ ๋ทฐ๋Š” ๋‹จ์ˆœํ™”, ๋ฐ์ดํ„ฐ ๋ณ€ํ˜•, ์ค‘๊ฐ„ ๊ฒฐ๊ณผ ์ง‘ํ•ฉ์˜ ์ƒ์„ฑ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ  SQL ์ฟผ๋ฆฌ์˜ ํšจ์œจ์„ฑ๊ณผ ๊ฐ€๋…์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ฟผ๋ฆฌ์˜ ๋ณต์žก๋„๋ฅผ ์ค„์ด๊ณ , ์ค‘๊ฐ„ ๋‹จ๊ณ„์˜ ๊ฒฐ๊ณผ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ๋„์ถœํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค.
๐Ÿ’ก
์ธ๋ผ์ธ ๋ทฐ ๋‚ด์—์„œ ORDER BY๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ตœ์ข… ๊ฒฐ๊ณผ ์ˆœ์„œ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ธŒ์ฟผ๋ฆฌ ๋‚ด ORDER BY๋Š” ์ตœ์ข… ๊ฒฐ๊ณผ์˜ ์ •๋ ฌ์„ ๊ฒฐ์ •ํ•˜๋Š” ๋ฉ”์ธ ์ฟผ๋ฆฌ์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ตœ์ข… ๊ฒฐ๊ณผ์˜ ์ •๋ ฌ์„ ์›ํ•œ๋‹ค๋ฉด ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ์•„๋‹Œ ๋ฉ”์ธ์ฟผ๋ฆฌ์— ORDER BY๋ฅผ ํฌํ•จ์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
ย 
์ธ๋ผ์ธ ๋ทฐ๋Š” ์ž„์‹œ ํ…Œ์ด๋ธ”์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ์ค‘๊ฐ„ ๊ฒฐ๊ณผ ์ง‘ํ•ฉ์„ ์ƒ์„ฑํ•จ์œผ๋กœ์จ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋‹จ์ˆœํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  1. ์ž„์‹œ ํ…Œ์ด๋ธ”์ฒ˜๋Ÿผ ์ž‘๋™: ์ธ๋ผ์ธ ๋ทฐ๋Š” ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ ์ž„์‹œ์ ์œผ๋กœ ์ƒ์„ฑ๋˜๋ฉฐ, ์ฟผ๋ฆฌ ์‹คํ–‰์ด ์™„๋ฃŒ๋˜๋ฉด ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
  1. ๋ณต์žกํ•œ ์ฟผ๋ฆฌ์˜ ๋‹จ์ˆœํ™”: ์ธ๋ผ์ธ ๋ทฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ์กฐ์ธ ์กฐ๊ฑด์ด๋‚˜ ํ•„ํ„ฐ๋ง ๋กœ์ง์„ ์„œ๋ธŒ์ฟผ๋ฆฌ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์ฃผ ์ฟผ๋ฆฌ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  1. ๋‹ค์ค‘ ์กฐ์ธ์˜ ์ค‘๊ฐ„ ๋‹จ๊ณ„: ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์„ ์กฐ์ธํ•  ๋•Œ, ์ธ๋ผ์ธ ๋ทฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ค‘๊ฐ„ ๊ฒฐ๊ณผ ์ง‘ํ•ฉ์„ ์ƒ์„ฑํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ถ”๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  1. ์ค‘๊ฐ„ ๊ฒฐ๊ณผ ์ƒ์„ฑ: ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ์ค‘๊ฐ„ ๋‹จ๊ณ„์˜ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ธฐ๋ณธ ๊ตฌ๋ฌธ
SELECT column1 , column2 FROM ( SELECT sub_column1 , sub_column2 FROM sub_table WHERE conditions ) AS inlineview_sub_column WHERE main_table_conditions;
์„ค๋ช…
  • inlineview_sub_column: ์ธ๋ผ์ธ ๋ทฐ์˜ ๋ณ„์นญ์œผ๋กœ, ์ธ๋ผ์ธ ๋ทฐ์˜ ๊ฒฐ๊ณผ๋ฅผ ์ฐธ์กฐํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • column1, column2: ๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ ์„ ํƒํ•˜๋ ค๋Š” ๋ฉ”์ธ ํ…Œ์ด๋ธ”์˜ ์—ด์ž…๋‹ˆ๋‹ค.
  • sub_column1, sub_column2: ์ธ๋ผ์ธ ๋ทฐ ๋‚ด์—์„œ ์„ ํƒํ•˜๋ ค๋Š” โ€œTable"์˜ ์—ด์ž…๋‹ˆ๋‹ค.
  • sub_table: ์ธ๋ผ์ธ ๋ทฐ ๋‚ด๋ถ€์˜ ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ์ฐธ์กฐํ•˜๋Š” ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค.
  • conditions: ์ธ๋ผ์ธ ๋ทฐ ๋‚ด์˜ ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„ํ„ฐ๋งํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ์กฐ๊ฑด๋“ค์ž…๋‹ˆ๋‹ค.
  • main_table_conditions: ์ธ๋ผ์ธ ๋ทฐ ์™ธ๋ถ€์˜ ๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„ํ„ฐ๋งํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ์กฐ๊ฑด๋“ค์ž…๋‹ˆ๋‹ค.
ย 
์˜ˆ์‹œ 1
โ€œemployeesโ€ ํ…Œ์ด๋ธ”์˜ ํ‰๊ท  ๊ธ‰์—ฌ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ์ธ๋ผ์ธ ๋ทฐ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ฉ”์ธ์ฟผ๋ฆฌ๋Š” ์ธ๋ผ์ธ ๋ทฐ์˜ ๊ฒฐ๊ณผ๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ์ง์›์˜ ํ‰๊ท  ๊ธ‰์—ฌ๋ณด๋‹ค ๋†’์€ ๊ธ‰์—ฌ๋ฅผ ๋ฐ›๋Š” ์ง์›์˜ ์ด๋ฆ„๊ณผ ๊ธ‰์—ฌ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์ฃผ๋กœ ์•Œ๋ ค์ง€์ง€ ์•Š์€ ๊ฐ’์„ ๋จผ์ € ์กฐํšŒํ•˜๊ฑฐ๋‚˜ ๊ณ„์‚ฐํ•œ ๋’ค ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
์•„๋ž˜ ์˜ˆ์‹œ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, โ€œemployeesโ€ ํ…Œ์ด๋ธ”์˜ ์ „์ฒด ์ง์›์˜ ํ‰๊ท  ๊ธ‰์—ฌ๋ฅผ ๋ฏธ๋ฆฌ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ๋Š” ์ด ๊ฐ’์„ ์•Œ๊ธฐ ์œ„ํ•ด ๋จผ์ € ํ‰๊ท  ๊ธ‰์—ฌ๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ๊ณ„์‚ฐ๋œ ํ‰๊ท  ๊ธ‰์—ฌ๋Š” ๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ ์ธ๋ผ์ธ ๋ทฐ์˜ ๊ฒฐ๊ณผ์ธ โ€œavgs.avg_salaryโ€์—์„œ ์ฐธ์กฐ๋˜๋ฉฐ, ํ•ด๋‹น ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ๊ธ‰์—ฌ๊ฐ€ ํ‰๊ท ๋ณด๋‹ค ๋†’์€ ์ง์›๋“ค์„ ํ•„ํ„ฐ๋งํ•˜์—ฌ ์ง์›์˜ ์ด๋ฆ„๊ณผ ๊ธ‰์—ฌ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
SELECT e.first_name , e.salary FROM `HR.employees` AS e ( SELECT AVG(salary) AS avg_salary FROM `HR.employees` ) AS avgs WHERE e.salary > avgs.avg_salary;
ย 
WITH์ ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ์ฟผ๋ฆฌ์˜ ๊ฐ€๋…์„ฑ์ด๊ธ‰์—ฌ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์ž„์‹œ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
WITH AverageSalary AS ( SELECT AVG(salary) AS avg_salary FROM `HR.employees` ) SELECT e.first_name , e.salary FROM `HR.employees` AS e JOIN AverageSalary avgs ON e.salary > avgs.avg_salary;
ย 
์˜ˆ์‹œ์˜ ๊ฒฐ๊ณผ๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์™€ WITH์ ˆ์„ ์‚ฌ์šฉํ•œ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
notion imagenotion image
ย 
ย 
์˜ˆ์‹œ 2
๋ถ€์„œ๋ณ„๋กœ ๊ฐ€์žฅ ๋†’์€ ๊ธ‰์—ฌ๋ฅผ ๋ฐ›๋Š” ์ง์›์˜ โ€œfirst_nameโ€, โ€œdepartment_idโ€, โ€œsalaryโ€๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
์•„๋ž˜ ์„œ๋ธŒ์ฟผ๋ฆฌ ์˜ˆ์‹œ๋Š” ๊ฐ โ€œdepartment_idโ€๋ณ„๋กœ ์ตœ๋Œ€ ๊ธ‰์—ฌ โ€œmax_salaryโ€๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๋ถ€์„œ๋ณ„๋กœ ๊ฐ€์žฅ ๋†’์€ ๊ธ‰์—ฌ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ๋Š” ๋ฐ˜ํ™˜๋œ ๊ฐ€์žฅ ๋†’์€ ๊ธ‰์—ฌ ๊ฐ’์„ JOIN์—ฐ์‚ฐ์„ ํ†ตํ•ด โ€œemployeesโ€ ํ…Œ์ด๋ธ”๊ณผ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค. JOIN ์—ฐ์‚ฐ์€ โ€œdepartment_idโ€์™€ โ€œsalaryโ€ ๊ธฐ์ค€์œผ๋กœ ์ด๋ฃจ์–ด์ง€๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ฐ ๋ถ€์„œ์—์„œ ๊ฐ€์žฅ ๋†’์€ ๊ธ‰์—ฌ๋ฅผ ๋ฐ›๋Š” ์ง์›์˜ ์ •๋ณด๋งŒ ํ•„ํ„ฐ๋งํ•˜์—ฌ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
SELECT e.first_name , e.department_id , e.salary FROM `HR.employees` AS e JOIN ( SELECT department_id , MAX(salary) AS max_salary FROM `HR.employees` GROUP BY department_id ) AS d ON e.department_id = d.department_id AND e.salary = d.max_salary;
ย 
๊ฐ ๋ถ€์„œ์˜ ์ตœ๋Œ€ ๊ธ‰์—ฌ๋ผ๋Š” ์•Œ๋ ค์ง€์ง€ ์•Š์€ ๊ธฐ์ค€๊ฐ’์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋ฏ€๋กœ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํ•ด๋‹น ๊ฐ’์„ ๋จผ์ € ๊ณ„์‚ฐํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์ด ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์•Œ๋ ค์ง€์ง€ ์•Š์€ ๊ธฐ์ค€์œผ๋กœ ๊ฒ€์ƒ‰ํ•  ๋•Œ ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค.
ย 
WITH์ ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด โ€œDepartmentMaxSalariesโ€๋ผ๋Š” ์ž„์‹œ ์ด๋ฆ„์œผ๋กœ ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ ์ง‘ํ•ฉ์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฟผ๋ฆฌ์˜ ๊ฐ€๋…์„ฑ์ด ํ–ฅ์ƒ๋˜๋ฉฐ, ๋ณต์žกํ•œ ์ฟผ๋ฆฌ์˜ ๊ตฌ์„ฑ์„ ์ข€ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
WITH DepartmentMaxSalaries AS ( SELECT department_id , MAX(salary) AS max_salary FROM `HR.employees` GROUP BY department_id ) SELECT e.first_name , e.department_id , e.salary FROM `HR.employees` AS e JOIN DepartmentMaxSalaries dms ON e.department_id = dms.department_id AND e.salary = dms.max_salary;
ย 
์˜ˆ์‹œ์˜ ๊ฒฐ๊ณผ๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์™€ WITH์ ˆ์„ ์‚ฌ์šฉํ•œ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
notion imagenotion image
ย 
์˜ˆ์‹œ 3
์ง์ฑ…๋ณ„ ํ‰๊ท  ๊ธ‰์—ฌ์™€ ํ•ด๋‹น ๊ธ‰์—ฌ์™€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ธ‰์—ฌ๋ฅผ ๋ฐ›๋Š” ์ง์›์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
์•„๋ž˜ ์„œ๋ธŒ์ฟผ๋ฆฌ ์˜ˆ์‹œ์—์„œ โ€œemployeesโ€ ํ…Œ์ด๋ธ”์—์„œ โ€œjob_idโ€๋ณ„ ํ‰๊ท  ๊ธ‰์—ฌ๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ โ€œivโ€๋กœ ๋ณ„์นญ์„ ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์ธ ์ฟผ๋ฆฌ์—์„œ๋Š” ํ•ด๋‹น ๊ฒฐ๊ณผ๋ฅผ JOIN์—ฐ์‚ฐํ•˜์—ฌ โ€œemployeesโ€ํ…Œ์ด๋ธ”๊ณผ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค. JOIN์€ ON์ ˆ์—์„œ โ€œjob_idโ€ ๊ธฐ์ค€์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋ฉฐ ๊ฐ โ€œjob_idโ€์— ๋Œ€ํ•œ ๊ฐ ์ง์›์˜ โ€œsalaryโ€์™€ โ€œavg_salaryโ€๊ฐ€ ํ•จ๊ป˜ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ORDER BY์ ˆ์—์„œ ๊ฐ ์ง์›์˜ โ€œsalaryโ€์™€ โ€œavg_salaryโ€์˜ ์ฐจ์ด๊ฐ€ ํฐ ์ˆœ์„œ๋Œ€๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜์—ฌ โ€œjob_idโ€์˜ ํ‰๊ท  ๊ธ‰์—ฌ์™€ ๊ฐ€์žฅ ํฐ ์ฐจ์ด๋ฅผ ๋ณด์ด๋Š” ์ง์›๋ถ€ํ„ฐ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
SELECT e.first_name , e.job_id , e.salary , iv.avg_salary FROM `HR.employees` AS e JOIN ( SELECT job_id , AVG(salary) AS avg_salary FROM `HR.employees` GROUP BY job_id ) AS iv ON e.job_id = iv.job_id ORDER BY ABS(e.salary - iv.avg_salary) DESC;
๊ฐ โ€œjob_idโ€์˜ โ€œavg_salaryโ€๋ผ๋Š” ์•Œ๋ ค์ง€์ง€ ์•Š์€ ๊ธฐ์ค€์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋ฏ€๋กœ, ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ธฐ์ค€๊ฐ’์„ ๋จผ์ € ๊ณ„์‚ฐํ•œ ํ›„ ๋ฉ”์ธ์ฟผ๋ฆฌ์—์„œ ํ•ด๋‹น ๊ฒฐ๊ณผ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
WITH์ ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ ์ง‘ํ•ฉ์„ โ€œJobAverageSalariesโ€๋ผ๋Š” ์ผ์‹œ์ ์ธ ์ด๋ฆ„์œผ๋กœ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์€ ์ฟผ๋ฆฌ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ด๋ฉฐ, ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์ค„์—ฌ์ค๋‹ˆ๋‹ค.
WITH JobAverageSalaries AS ( SELECT job_id , AVG(salary) AS avg_salary FROM `HR.employees` GROUP BY job_id ) SELECT e.first_name , e.job_id , e.salary , jas.avg_salary FROM `HR.employees` AS e JOIN JobAverageSalaries AS jas ON e.job_id = jas.job_id ORDER BY ABS(e.salary - jas.avg_salary) DESC;
ย 
์˜ˆ์‹œ์˜ ๊ฒฐ๊ณผ๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์™€ WITH์ ˆ์„ ์‚ฌ์šฉํ•œ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
notion imagenotion image
ย 

10.2.3. ์ค‘์ฒฉ

์ค‘์ฒฉ ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ํ•˜๋‚˜์˜ SQL ์ฟผ๋ฆฌ ์•ˆ์— ๋‹ค๋ฅธ ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ํฌํ•จ๋œ ์ฟผ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์ค‘์ฒฉ ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์™ธ๋ถ€ ์ฟผ๋ฆฌ์˜ ์กฐ๊ฑด์„ ํ‰๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•ด ์ฃผ๋กœ WHERE์ ˆ์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, ์ค‘์ฒฉ ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์™ธ๋ถ€ ์ฟผ๋ฆฌ์˜ ์กฐ๊ฑด์— ๋”ฐ๋ผ ์‹คํ–‰๋˜๋ฉฐ, ์„œ๋ธŒ์ฟผ๋ฆฌ ๋‚ด๋ถ€์—์„œ๋Š” ์™ธ๋ถ€ ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋‚˜ ์กฐ๊ฑด์„ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.
์ค‘์ฒฉ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•œ ์ฟผ๋ฆฌ ์•ˆ์—์„œ ์—ฌ๋Ÿฌ ์ˆ˜์ค€์˜ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณต์žกํ•œ ์กฐ๊ฑด์„ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜, ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์–‘ํ•œ ๊ณ„์‚ฐ์ด๋‚˜ ๋น„๊ต๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 
๊ธฐ๋ณธ ๊ตฌ๋ฌธ
SELECT main_column1 FROM main_table WHERE main_column2 operator ( SELECT sub_column FROM sub_table WHERE sub_condition );
์„ค๋ช…
  • main_column1: ์™ธ๋ถ€ ์ฟผ๋ฆฌ์—์„œ ์„ ํƒํ•  ์ฃผ์š” ์—ด์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • main_table: ์™ธ๋ถ€ ์ฟผ๋ฆฌ์˜ ์ฃผ ํ…Œ์ด๋ธ”์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • main_column2: ์™ธ๋ถ€ ์ฟผ๋ฆฌ์—์„œ ์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉํ•  ์ฃผ์š” ์—ด์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • operator: ๋น„๊ต ์—ฐ์‚ฐ์ž(์˜ˆ: =, >, <, IN ๋“ฑ)๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • sub_column: ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ์„ ํƒํ•  ์—ด์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • sub_table: ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ํ…Œ์ด๋ธ”์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • sub_condition: ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์กฐ๊ฑด์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
ย 
์˜ˆ์‹œ 1
์ค‘์ฒฉ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด โ€œemployeesโ€ ํ…Œ์ด๋ธ”์—์„œ 2005๋…„ 1์›” 1์ผ ์ดํ›„ ์ž…์‚ฌํ•œ ์ง์›๋“ค์˜ ํ‰๊ท  ๊ธ‰์—ฌ๋ณด๋‹ค ๊ธ‰์—ฌ๊ฐ€ ๋†’์€ ์ง์›์˜ ์•„์ด๋””, ์„ฑ, ์ด๋ฆ„, ์ž…์‚ฌ์ผ, ๊ธ‰์—ฌ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.
SELECT employee_id , first_name , last_name , hire_date , salary FROM `HR.employees` WHERE salary > ( SELECT AVG(salary) FROM `HR.employees` WHERE hire_date > '2005-01-01' );
notion imagenotion image
ย 
์˜ˆ์‹œ 2
์ค‘์ฒฉ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด โ€œdepartmentsโ€ ํ…Œ์ด๋ธ”์—์„œ โ€œmanger_idโ€ ์ปฌ๋Ÿผ์ด NULL์ธ โ€œdepartment_idโ€๋ฅผ ์กฐํšŒํ•˜๊ณ , โ€œemployeesโ€ ํ…Œ์ด๋ธ”์—์„œ ํ•ด๋‹น โ€œdepartment_idโ€์— ์†ํ•˜์ง€ ์•Š์€ ์ง์›์˜ โ€œdepartment_idโ€์™€ โ€œemployee_idโ€๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.
SELECT department_id , employee_id FROM `HR.employees` WHERE department_id NOT IN ( SELECT department_id FROM `HR.departments` WHERE manager_id IS NULL );
notion imagenotion image
ย 
์˜ˆ์‹œ 3
percentile ํ•จ์ˆ˜(๋ฐฑ๋ถ„์œ„ ํ•จ์ˆ˜)๋ฅผ ์ด์šฉํ•˜์—ฌ โ€œemployeesโ€ ํ…Œ์ด๋ธ”์—์„œ ์ง์›๋“ค์˜ ๊ธ‰์—ฌ(โ€salaryโ€)๊ฐ€ ์ƒ์œ„ 25%์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’, ์ฆ‰ 75๋ฒˆ์งธ ๋ฐฑ๋ถ„์œ„์ˆ˜๋ฅผ ์ฐพ๊ณ , ์ด๋ณด๋‹ค ๋†’์€ ๊ธ‰์—ฌ๋ฅผ ๋ฐ›๋Š” ์ง์›๋“ค์˜ ์•„์ด๋””(โ€employee_idโ€)์™€ ๊ธ‰์—ฌ(โ€salaryโ€)๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.
SELECT employee_id , salary FROM `HR.employees` WHERE salary > ( SELECT percentile_cont(salary, 0.75) OVER() FROM `HR.employees` LIMIT 1 ) ORDER BY salary DESC;
notion imagenotion image
ย 

10.2.4. IN

IN ์—ฐ์‚ฐ์ž๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ ์ง‘ํ•ฉ ์•ˆ์— ํŠน์ • ๊ฐ’์„ ํฌํ•จํ•˜๊ฑฐ๋‚˜ ํฌํ•จํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. NOT IN ์—ฐ์‚ฐ์ž๋Š” ๊ทธ ๋ฐ˜๋Œ€์˜ ์กฐ๊ฑด์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
ย 
๊ธฐ๋ณธ ๊ตฌ๋ฌธ
value [ NOT ] IN ( subquery )
ย 
์˜ˆ์‹œ 1
๋‹ค์Œ์€ ์ง์—…๋ช…์ด 'Sales Representative', 'Marketing Manager'์ธ ์ง์›์˜ ์•„์ด๋””์™€, ์ด๋ฆ„์„ ์ถœ๋ ฅํ•˜๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.
SELECT employee_id , first_name || ' ' || last_name AS full_name FROM `HR.employees` WHERE 1=1 , job_id IN ( SELECT job_id FROM `HR.jobs` WHERE 1=1 , job_title IN ('Sales Representative', 'Marketing Manager') );
WITH SelectedJobs AS ( SELECT job_id FROM `HR.jobs` WHERE job_title IN ('Sales Representative', 'Marketing Manager') ) SELECT e.employee_id , e.first_name || ' ' || e.last_name AS full_name FROM `HR.employees` AS e WHERE 1=1 , e.job_id IN ( SELECT job_id FROM SelectedJobs );
notion imagenotion image
ย 
์˜ˆ์‹œ 2
โ€œdepartmentsโ€ ํ…Œ์ด๋ธ”์—์„œ ํŠน์ • ๋ถ€์„œ 'Sales', 'Marketing'์— ์†ํ•˜์ง€ ์•Š์€ ์ง์›์„ ์ฐพ๋Š” NOT IN ์„œ๋ธŒ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.
SELECT employee_id, , first_name || ' ' || last_name AS full_name , department_id FROM `HR.employees` WHERE department_id NOT IN ( SELECT department_id FROM `HR.departments` WHERE 1=1 , department_name IN ('Sales', 'Marketing') );
WITH ExcludedDepartments AS ( SELECT department_id FROM `HR.departments` WHERE department_name IN ('Sales', 'Marketing') ) SELECT e.employee_id , e.first_name || ' ' || e.last_name AS full_name , e.department_id FROM `HR.employees` AS e WHERE 1=1 , e.department_id NOT IN ( SELECT department_id FROM ExcludedDepartments );
notion imagenotion image
ย 

10.2.5. EXISTS

EXISTS๋Š” SQL์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋…ผ๋ฆฌ ์—ฐ์‚ฐ์ž๋กœ, ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
EXISTS ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์ฃผ๋กœ WHERE ์ ˆ์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, ์™ธ๋ถ€ ์ฟผ๋ฆฌ์˜ ๊ฐ ํ–‰์— ๋Œ€ํ•ด ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ฐธ ๋˜๋Š” ๊ฑฐ์ง“์„ ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ธŒ์ฟผ๋ฆฌ ๋‚ด์—์„œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ SELECT ๋ฌธ์ด ์•„๋‹ˆ๋ผ ๋‹จ์ˆœํ•œ ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์œผ๋ฉด TRUE๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฒฐ๊ณผ๊ฐ€ ๋น„์–ด์žˆ์œผ๋ฉด FALSE๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
ย 
๊ธฐ๋ณธ ๊ตฌ๋ฌธ
SELECT ์ ˆ์—์„œ์˜ ๊ตฌ๋ฌธ
SELECT EXISTS ( SELECT 'found' FROM sub_table WHERE condition ) AS exists_result;
ย 
WHERE ์ ˆ์—์„œ์˜ ๊ตฌ๋ฌธ
SELECT column1 , column2 FROM main_table WHERE EXISTS ( SELECT 'found' FROM sub_table WHERE condition );
์„ค๋ช…
  • column1, column2: ๋ฐ˜ํ™˜ํ•  ์—ด์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • main_table: ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๊ธฐ๋ณธ ํ…Œ์ด๋ธ”์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • sub_table: ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•  ๋‘ ๋ฒˆ์งธ ํ…Œ์ด๋ธ”์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • found: ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉ๋œ ๊ฐ’์œผ๋กœ, ์‹ค์ œ๋กœ๋Š” ํ•ญ์ƒ ์ฐธ(TRUE)์œผ๋กœ ํ‰๊ฐ€๋˜๋Š” ์ž„์˜์˜ ๊ฐ’์ž…๋‹ˆ๋‹ค. ์ด ๊ฐ’์€ EXISTS ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ์กฐ๊ฑด์ด ์ฐธ์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • condition: ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•  ์กฐ๊ฑด์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
ย 
์˜ˆ์‹œ
EXISTS ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด โ€œdepartmentsโ€ ํ…Œ์ด๋ธ”์˜ ๋ถ€์„œ ์•„์ด๋””๊ฐ€ 50์ธ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ํ–‰์ด ํ•˜๋‚˜๋ผ๋„ ์กด์žฌํ•œ๋‹ค๋ฉด, โ€œemployeesโ€ ํ…Œ์ด๋ธ”์˜ ์ง์› ์•„์ด๋””, ์ง์—… ์•„์ด๋””, ๋ถ€์„œ ์•„์ด๋””๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.
SELECT employee_id , job_id , department_id FROM `HR.employees` WHERE EXISTS ( SELECT 1 FROM `HR.departments` WHERE department_id = 50 )
notion imagenotion image
ย 

10.2.6. ์ƒ๊ด€

์ƒ๊ด€ ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ์™ธ๋ถ€ ์ฟผ๋ฆฌ์˜ ์—ด์„ ์ฐธ์กฐํ•˜์—ฌ ์‹คํ–‰๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ๋‹จ์ˆœํžˆ ์™ธ๋ถ€ ์ฟผ๋ฆฌ์—์„œ ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ, ์ƒ๊ด€ ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ์™ธ๋ถ€ ์ฟผ๋ฆฌ์™€ ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ์„œ๋กœ ์—ฐ๊ด€์„ฑ์„ ๊ฐ–๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์™ธ๋ถ€ ์ฟผ๋ฆฌ์˜ ์‹คํ–‰์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
ย 
SELECT ์ ˆ์—์„œ์˜ ๊ตฌ๋ฌธ
SELECT m.column1 , m.column2 ( SELECT s.value FROM sub_table s WHERE s.id = m.id ) AS subquery_result FROM main_table AS m;
ย 
WHERE ์ ˆ์—์„œ์˜ ๊ตฌ๋ฌธ
SELECT m.column1 , m.column2 FROM main_table m WHERE operator ( SELECT s.value FROM sub_table s WHERE m.id = s.id );
์„ค๋ช…
  • main_table (m): ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๊ธฐ๋ณธ ํ…Œ์ด๋ธ”์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • sub_table (s): ์„œ๋ธŒ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•  ๋‘ ๋ฒˆ์งธ ํ…Œ์ด๋ธ”์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • m.id: ๋ฉ”์ธ ํ…Œ์ด๋ธ” โ€œmain_tableโ€์˜ id ์—ด์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
  • s.id: ์„œ๋ธŒ ํ…Œ์ด๋ธ” โ€œsub_tableโ€์˜ id ์—ด์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ์—ด์€ ์™ธ๋ถ€ ์ฟผ๋ฆฌ์˜ ๋ฉ”์ธ ํ…Œ์ด๋ธ”๊ณผ ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ์„œ๋ธŒ ํ…Œ์ด๋ธ”์„ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • operator: ๋น„๊ต ์—ฐ์‚ฐ์ž(์˜ˆ: =, >, <, IN ๋“ฑ)๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
ย 
์˜ˆ์‹œ
์ƒ๊ด€ ์„œ๋ธŒ์ฟผ๋ฆฌ ๋‚ด์˜ โ€œjob_historyโ€ ํ…Œ์ด๋ธ”์˜ ์ง์› ์•„์ด๋””์™€ ์™ธ๋ถ€ ์ฟผ๋ฆฌ์˜ โ€œemployeesโ€ ํ…Œ์ด๋ธ”์˜ ์ง์› ์•„์ด๋””๊ฐ€ ๊ฐ™์€ ์ง์›์˜ ์„ฑ๊ณผ ์ด๋ฆ„ ๋ฐ ์ง์› ์•„์ด๋””๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.
SELECT e.first_name , e.last_name , e.employee_id FROM `HR.employees` AS e WHERE EXISTS ( SELECT employee_id FROM `HR.job_history` AS j WHERE j.employee_id = e.employee_id );
notion imagenotion image
๋‹ค์Œ๊ณผ ๊ฐ™์ด, โ€œemployeesโ€ ํ…Œ์ด๋ธ”์˜ ์ง์› ์•„์ด๋””(โ€œemployee_idโ€) ์ค‘ โ€œjob_historyโ€ ํ…Œ์ด๋ธ”์— ์†ํ•œ ์ง์› ์•„์ด๋””(โ€œemployee_idโ€)์™€ ์ผ์น˜ํ•˜๋Š” ์‚ฌ์›์˜ ์ด๋ฆ„(โ€œfirst_nameโ€), ์„ฑ(โ€last_nameโ€) ๋ฐ ์ง์› ์•„์ด๋””(โ€employee_idโ€)๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ย 

10.2.7. ARRAY

๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํŠน๋ณ„ํ•œ ์„œ๋ธŒ์ฟผ๋ฆฌ ํ‘œํ˜„ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ๊ฐ€ 0ํ–‰ ์ผ ๋•Œ ๋นˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  NULL ๋ฐฐ์—ด์€ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
ARRAY ์„œ๋ธŒ์ฟผ๋ฆฌ๋Š” ๋ฐ˜ํ™˜ ๋ฐฐ์—ด์— ๋Œ€ํ•œ ์œ ํ˜•์ด ์ปฌ๋Ÿผ ๋‹น ๋‹จ์ผํ•œ ์œ ํ˜•์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. SELECT AS STRUCT ์™€ ํ•จ๊ป˜ ์ž‘์„ฑํ•˜๋ ค๋ฉด SELECT๋ชฉ๋ก์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์—ด์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฐฐ์—ด ์„œ๋ธŒ์ฟผ๋ฆฌ์˜ ๊ฐ’์€ STRUCT์˜ ๋ฐฐ์—ด ๊ตฌ์กฐ๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. SELECT AS ์—†์ด ์—ฌ๋Ÿฌ ์—ด์„ ์„ ํƒํ•  ๊ฒฝ์šฐ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
ย 
๊ธฐ๋ณธ ๊ตฌ๋ฌธ
ARRAY ( subquery )
ย 
์˜ˆ์‹œ 1
โ€œjob_idโ€๊ฐ€ 'SA_MAN'์ธ ์ง์›๋“ค์˜ โ€œfirst_nameโ€์„ ๋ฐฐ์—ด๋กœ ์„ ํƒํ•˜๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.
SELECT ARRAY( SELECT first_name FROM `HR.employees` WHERE job_id='SA_MAN' ) AS SA_MAN;
WITH SaManEmployees AS ( SELECT ARRAY_AGG(first_name) AS SA_MAN FROM `HR.employees` WHERE job_id = 'SA_MAN' ) SELECT SA_MAN FROM SaManEmployees;
notion imagenotion image
ย 
์˜ˆ์‹œ 2
๋ถ€์„œ๋ณ„ ์ง์› ๋ชฉ๋ก์„ ๋ฐฐ์—ด๋กœ ์ƒ์„ฑํ•˜๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. GROUP BY์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ARRAY_AGG๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
SELECT department_id , ARRAY_AGG(first_name) AS employees_name FROM `HR.employees` GROUP BY department_id;
WITH DepartmentEmployees AS ( SELECT department_id , ARRAY_AGG(first_name) AS employees_name FROM `HR.employees` GROUP BY department_id ) SELECT department_id , employees_name FROM DepartmentEmployee;
notion imagenotion image