4. μλμ° ν¨μ
μλμ° ν¨μμ κ°μ
μλμ° ν¨μ κΈ°μ΄ κ°λ
- μλμ°(WINDOW)λ 'μ 체 λ°μ΄ν° μ€ νΉμ λΆλΆλ§ λ°μ·ν΄μ λ³Έλ€'λΌλ κ²μμ μ λ, λΆμ ν¨μλΌκ³ λ λΆλ¦Ό
- μΉΌλΌμ κΈ°μ€μΌλ‘ νμ λ°μ΄ν°λ₯Ό νν°λ§νκ±°λ 쑰건κ°μ λ°ννλ μ ν΅μ κ°λ κ³Ό λ¬λ¦¬ μ 체 λ°μ΄ν°μ νλ€μ νν°μ μΌλ‘ λλ μμμ μ€μ νκ³ , κ·Έ μμ μμμ νκ³Ό ν κ°μ κ΄κ³λ₯Ό μ½κ² μ μνκΈ° μν΄ λ§λ€μ΄μ§
- κ΄κ³ν λ°μ΄ν°λ² μ΄μ€ SQLμ λ¨μ (νκ³Ό ν κ°μ κ΄κ³ μ μ λ° λΉκ΅κ° μ΄λ €μ)μ 보μνκΈ° μν΄ λ§λ€μ΄μ§
μλμ° ν¨μ μ’ λ₯
- μμ ν¨μ: ROW_NUMBER(), RANK(), DENSE_RANK()
- μ§κ³ ν¨μ: SUM(), AVG(), COUNT(), MAX(), MIN(), (μ§κ³ ν¨μ + OVER)
- ν μμ κ΄λ ¨ ν¨μ(μ€νμ ν¨μ): LAG(n), LEAD(n), FIRST_VALUE, LAST_VALUE, NTH_VALUE(n)
- λΉμ¨ ν¨μ: CUME_DIST(), PERCENT_RANK(), NTILE(n), RATIO_TO_REPORT,
- λΆμ ν¨μ(SQLD λ²μ μλ): CORE, COVAR_POP, COVAR_SAMP, STDDEV, STDDEV_POP, STDDEV_SAMP, VARIANCE, VAR_POP, VAR_SAMP, REGR_(LINEAR REGRESSION), REGR_SLOPE, REGR_INTERCEPT, REGR_COUNT, REGR_R2, REGR_AVGX, REGR_AVGY, REGR_SXX, REGR_SYY, REFILSXY
μλμ° ν¨μ νμ
SELECT
WINDOW_FUNCTION(ARGUMENTS)
OVER ([PARTITION BY μΉΌλΌ] [ORDER BY μ ] [WINDOWING μ ])
FROM
ν
μ΄λΈλͺ
;
- OVER ν€μλ νμλ‘ ν¬ν¨ (GROUP BY μμ΄λ μ§κ³κ° κ°λ₯)
- ROWSλ 물리μ μΈ κ²°κ³Ό ν μ, RANGEλ λ Όλ¦¬μ κ°μ μν λ²μ => λ μ€ νλ μ νν΄μ μ¬μ©
- WINDOW_FUNCTION: κΈ°μ‘΄μ μ¬μ©νλ ν¨μ νΉμ μλ‘κ² WINDOW ν¨μμ©μΌλ‘ μΆκ°λ ν¨μ
- ARGUMENTS(μΈμ): ν¨μμ λ°λΌ 0~Nκ°μ μΈμ μ§μ
- PARTITION BY μ : μ 체 μ§ν©μ κΈ°μ€μ λ°λΌ μκ·Έλ£ΉμΌλ‘ λλ μ μμ
- ORDER BY μ : μ΄λ€ νλͺ©μ λν΄ μμλ₯Ό μ§μ νκ³ μ ν λ ORDER BY μ κΈ°μ
- WINDOWING μ : ν¨μμ λμμ΄ λλ ν κΈ°μ€μ λ²μ(κ³μ°μ΄ λλ λ²μ)λ₯Ό μΈλ°νκ² μ§μ (SQL Serverμμλ μ§μ X)
μμ ν¨μ
ROW_NUMBER()
- SQLμμ κ° νμ κ³ μ ν μμ λ²νΈλ₯Ό ν λΉνλ μλμ° ν¨μ
- μ£Όλ‘ λ°μ΄ν°μ μμλ₯Ό λ§€κΈ°κ±°λ νΉμ κΈ°μ€μ λ°λΌ νμ λμ΄ν λ μ¬μ©
- νμ : ROW_NUMBER() OVER (PARTITION BY [νν°μ
κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€])
- ROW_NUMBER() λ€μ OVER μ μ΄ μ€λ©° λ κ°μ§ μ΅μ μ κ΄νΈλ‘ λ¬Άμ΄ μ¬μ©
- PARTITION BY [νν°μ κΈ°μ€]: νμ κΈ°μ€μΌλ‘ ꡬλΆν΄ λλλ μ΅μ . μλ΅ μ μ 체 κ²°κ³Ό μ§ν©μ λν΄ μμ λ§€κΉ.
- ORDER BY [μ λ ¬ κΈ°μ€]: μμλ₯Ό λ§€κΈΈ λ μ¬μ©ν μ λ ¬ κΈ°μ€μΌλ‘ λ°λμ μ§μ ν΄μΌ ν¨. (μ§μ νμ§ μμ μ μλ¬)
- λμΌν μμλ₯Ό μ§μ νκ³ μΆμ λ: RANK(), DENSE_RANK()λ₯Ό μ¬μ©νκ±°λ, ORDER BY μ μ μΆκ°λ‘ μΉΌλΌ μ§μ
RANK()
- ROW_NUMBER() ν¨μμ²λΌ μμλ₯Ό λ§€κΈΈ λ μ¬μ©λμ§λ§, λμΌν κ°μ΄ μμ λ λμΌν μμλ₯Ό λΆμ¬νκ³ λ€μ μμλ₯Ό 건λλ.
- νμ : RANK() OVER (PARTITION BY [νν°μ
κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€])
- RANK() λ€μ OVER μ μ΄ μ€λ©°, μλ λ κ°μ§ μ΅μ μ κ΄νΈλ‘ λ¬Άμ΄ μ¬μ©
- PARTITION BY [νν°μ κΈ°μ€], ORDER BY [μ λ ¬ κΈ°μ€] μ΅μ μ ROW_NUMBER ν¨μμ λμΌ
DENSE_RANK()
- ROW_NUMBER(), RANK() ν¨μμ²λΌ μμλ₯Ό λ§€κΈΈ λ μ¬μ©λμ§λ§, λμΌν κ°μ΄ μμ λ λμΌν μμλ₯Ό λΆμ¬νκ³ λ€μ μμλ₯Ό 건λλ°μ§ μκ³ μ°μλ μμλ₯Ό λ§€κΉ
- νμ : DENSE_RANK() OVER (PARTITION BY [νν°μ κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€])
μ§κ³ ν¨μ
SUM()
- μ§μ λ μΉΌλΌμ μ«μ κ°λ€μ κ³μ°
- NULL κ°μ 무μλλ―λ‘, NULLμ 0μΌλ‘ μ²λ¦¬νκ³ μΆλ€λ©΄ COALESCE νΉμ NVL ν¨μ ν¨κ» μ¬μ©
μ°Έκ³ ) COALESCE, NVL μ°¨μ΄μ
- NVLμ μ€λΌν΄ μ μ©, COALESCEλ SQL νμ€
- NVLμ μ νν λ κ°μ λ§€κ°λ³μλ§ μ¬μ©νμ§λ§ COALESCEλ λ κ° μ΄μμ λ§€κ°λ³μλ₯Ό μ¬μ©
- NVLμ λ λ²μ§Έ λ§€κ°λ³μλ₯Ό νμ νκ°, COALESCEλ NULLμ΄ μλ κ°μ μ°ΎμΌλ©΄ κ·Έ μ΄ν λ§€κ°λ³μλ νκ°νμ§ μμ(Short-circuit evaluation)
AVG()
- νΉμ μΉΌλΌμ νκ· κ°μ κ³μ°
- NULL κ°μ 무μλλ―λ‘, NULLμ 0μΌλ‘ μ²λ¦¬νκ³ μΆλ€λ©΄ COALESCE νΉμ NVL ν¨μ ν¨κ» μ¬μ©
COUNT()
- νμ κ°μλ₯Ό κ³μ°νλ μ§κ³ ν¨μ, νΉμ μΉΌλΌμ΄λ μ 체 νμ κ°μλ₯Ό μΈλ λ° μ¬μ©
- NULL κ°μ 무μλλ―λ‘, NULLμ 0μΌλ‘ μ²λ¦¬νκ³ μΆλ€λ©΄ COALESCE νΉμ NVL ν¨μ ν¨κ» μ¬μ©
MAX()
- νΉμ μΉΌλΌμ κ°μ₯ ν° κ°μ μ°Ύλ λ° μ¬μ©, μ£Όλ‘ μμΉ λ°μ΄ν°, λ μ§, λ¬Έμμ΄ λ± λΉκ΅ κ°λ₯ν κ°μ λν΄ μ μ©
- NULL κ°μ 무μλ¨
MIN()
- νΉμ μΉΌλΌμ κ°μ₯ μμ κ°μ μ°Ύλ λ° μ¬μ©
- NULL κ°μ 무μλ¨
μ§κ³ ν¨μ + OVER
- μ§κ³ ν¨μμ OVER μ μ ν¨κ» μ¬μ©νλ©΄ μ§κ³ ν¨μκ° μλμ° ν¨μλ‘ μλνμ¬ λ°μ΄ν°μ νΉμ 'μλμ°' λλ 'νλ μ' λ΄μμ κ³μ° μν
- OVER μ μ PARTITION BYμ ORDER BYλ₯Ό ν¬ν¨ν μ μμ => μ§κ³ ν¨μμ μ μ© λ²μ μ μ
ν μμ κ΄λ ¨ ν¨μ(μ€νμ ν¨μ)
LAG(n)
- λ°μ΄ν° μ§ν© λ΄μμ νΉμ νμ κΈ°μ€μΌλ‘ nλ²μ§Έ μ΄μ νμ κ°μ κ°μ Έμ€λ λ° μ¬μ©
- λ°μ΄ν° λΆμκ³Ό μκ³μ΄ μ²λ¦¬μμ μ μ© (ex. μ£Όμ λ°μ΄ν°μμ κ°κ²© λ³νλ μμ, μλ³ λ§€μΆμ μ¦κ°, λΆμλ³ λ§€μΆ μμ λΉκ΅ λ° λΆμ λ±)
- νμ : LAG(μΉΌλΌλͺ , [μμΉ n], [μ΄μ νμ΄ μμ λ λ°νν κ°]) OVER (PARTITION BY [νν°μ κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€])
LEAD(n)
- LAG(n) ν¨μμ λ°λ, λ°μ΄ν° μ§ν© λ΄μμ νΉμ νμ κΈ°μ€μΌλ‘ nλ²μ§Έ μ΄ν νμ κ°μ κ°μ Έμ€λ λ° μ¬μ©
- νμ : LEAD(μΉΌλΌλͺ , [μμΉ n], [μ΄ν νμ΄ μμ λ λ°νν κ°]) OVER (PARTITION BY [νν°μ κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€])
FIRST_VALUE()
- λ°μ΄ν° μ§ν© λλ νν°μ λ΄μμ 첫 λ²μ§Έ κ°μ λ°ν
- νμ : FIRST_VALUE(μΉΌλΌλͺ ) OVER (PARTITION BY [νν°μ κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€] [WINDOW FRAME])
LAST_VALUE()
- λ°μ΄ν° μ§ν© λλ νν°μ λ΄μμ λ§μ§λ§ κ°μ λ°ν
- νμ : LAST_VALUE(μΉΌλΌλͺ ) OVER (PARTITION BY [νν°μ κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€] [WINDOW FRAME])
- κΈ°λ³Έμ μΌλ‘ νμ¬ νκΉμ§λ§μ λ°μ΄ν°λ₯Ό κ³ λ €νκΈ° λλ¬Έμ, LAST_VALUE() ν¨μμμ νλ μμ μ ν΅ν΄ μ΄λλΆν° μ΄λκΉμ§μ κ°μ μ½μ΄μΌ νλμ§ λͺ
μν΄μ£Όμ΄μΌ ν¨
- ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING (λͺ¨λ ROWμ λν΄ νν°μ μ 첫 λ²μ§Έ νλΆν° μμν΄μ νν°μ μ λ§μ§λ§ νκΉμ§)
- ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW (νμ¬κΉμ§μ λͺ¨λ ν)
- ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING (νμ¬ νκ³Ό κ·Έ μ νμ ν)
NTH_VALUE(n)
- λ°μ΄ν° μ§ν© λλ νν°μ λ΄μμ μ§μ λ μμμ κ°μ λ°ν
- νμ : NTH_VALUE(μΉΌλΌλͺ , n) OVER (PARTITION BY [νν°μ κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€] [WINDOW FRAME])
λΉμ¨ ν¨μ
CUME_DIST()
- λμ λΆν¬ ν¨μλ‘, λ°μ΄ν° μ§ν© λ΄μμ νΉμ κ° μ΄νμ κ°λ€μ΄ μ°¨μ§νλ λΉμ¨μ κ³μ°ν΄ 0κ³Ό 1 μ¬μ΄μ κ°μ λ°ν (νΉμ κ°μ λμ λΆν¬λ₯Ό κ³μ°νλ λ° μ¬μ©)
- κ°μ λμ λΉμ¨μ΄ μλ νμ κ°μμ λ°λ₯Έ λμ λΉμ¨μμ μ£Όμ
- νμ : CUME_DIST() OVER (PARTITION BY [νν°μ κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€])
PERCENT_RANK()
- λ°μ΄ν° μ§ν© λ΄μμ κ° κ°μ λ°±λΆμ μμλ₯Ό κ³μ°νμ¬ μ²« λ²μ§Έ νμ λ°±λΆμ μμλ 0μΌλ‘ μμν΄ 0κ³Ό 1 μ¬μ΄μ κ°μ λ°ν
- PERCENT_RANK() = μμ - 1 / μ 체 νμ κ°μ - 1
- PERCENT_RANK()λ μμ κΈ°λ°μΌλ‘ 0λΆν° μμνκ³ , CUME_DIST()λ λμ λΆν¬ κΈ°λ°μΌλ‘ 0λ³΄λ€ ν° κ°λΆν° μμνλ€λ μ μ΄ λ€λ¦
- νμ : PERCENT_RANK() OVER (PARTITION BY [νν°μ κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€])
NTILE(n)
- λ°μ΄ν° μ§ν©μ n κ°μ λμΌν ν¬κΈ°μ κ·Έλ£ΉμΌλ‘ λλκ³ , κ° νμ κ·Έλ£Ή λ²νΈλ₯Ό λΆμ¬
- νμ : NTILE(n) OVER (PARTITION BY [νν°μ κΈ°μ€] ORDER BY [μ λ ¬ κΈ°μ€])
5. Top N 쿼리
ROWNUM μλ μΉΌλΌ
μλ μΉΌλΌ(Pseudo Column)
- λ°μ΄ν°λ² μ΄μ€ μμ€ν μμ μ 곡νλ νΉλ³ν μ’ λ₯μ μΉΌλΌμΌλ‘ μ€μ λ‘ μ‘΄μ¬νλ λ°μ΄ν°κ° μλλΌ, κ°μμ μΉΌλΌμ λ§λ€μ΄ 쿼리μμ μΌλ° μΉΌλΌμ²λΌ μ¬μ© κ°λ₯
- μλ μΉΌλΌμ νΉμ§: λ°μ΄ν°λ² μ΄μ€ μμ€ν μ μν΄ μλ μμ± λ° κ΄λ¦¬, μ½κΈ° μ μ©, 쿼리 μ€ν μ λμ μΌλ‘ κ° ν λΉ
- μ€λΌν΄μ μλ μΉΌλΌ: ROWNUM(쿼리 κ²°κ³Όμ κ° νμ μμ°¨μ λ²νΈ λΆμ¬), ROWID(κ° νμ κ³ μ μλ³μ), LEVEL(κ³μΈ΅μ 쿼리μμ νΈλ¦¬ λ 벨 νμ), CURRVAL / NEXTVAL(μνμ€ κ΄λ ¨ μμ μ μ¬μ©)
- SQL Serverμ μλ μΉΌλΌ: @@ERROR, @@IDENTITY
- MySQLμ μλ μΉΌλΌ: FOUND_ROWS(), ROW_COUNT()
ROWNUM
- κ²°κ³Ό μ§ν©μμ κ° νμ μμ°¨μ μΌλ‘ κ³ μ ν λ²νΈ ν λΉ (첫 λ²μ§Έ νμ 1, λ λ²μ§Έ νμ 2, ... )
- 쿼리 μ€ν μμμ λ°λΌ λΆμ¬λλ―λ‘ κ²°κ³Ό μ§ν©μ ν μμκ° μ€μν κ²½μ° μ¬μ©
- νΉλ³ν νμ λ°λ‘ μμ΄ νλμ μΉΌλΌμ²λΌ μ¬μ© (ex. SELECT ROWNUM, EMPNO, ENAME FROM EMP)
TOP μ
SQL Serverμμ μ¬μ©νλ TOPμ
- κ²°κ³Ό μ§ν©μ μμ Nκ°μ νμ λ°ννλ λ° μ¬μ©λλ μ
- κ²°κ³Ό μ§ν© ν¬κΈ° μ ν, 쿼리μ μ±λ₯ μ΅μ ν, νΉμ μμ νλ§ μ νν λ μ μ©
- SELECT λ¬Έκ³Ό ν¨κ» μ¬μ©λμ΄ κ²°κ³Ό μ§ν©μμ μμ Nκ°μ ν / μμ N%μ ν μ ν, ORDER BY μ κ³Ό ν¨κ» μ¬μ©νλ©΄ νΉμ κΈ°μ€μ λ°λΌ μμ Nκ°μ ν μ ν κ°λ₯
- μμ : SELECT TOP(3) EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO = 20 ORDER BY SAL DESC;
μ€λΌν΄μμ μ¬μ©νλ ROW LIMITING μ
- κ²°κ³Ό μ§ν©μ ν μλ₯Ό μ ννλ λ° μ¬μ©λλ μ
- FETCH FIRST, OFFSET μ μ μ¬μ©νμ¬ κ²°κ³Ό μ§ν©μ μμ Nκ°μ νμ μ ννκ±°λ νΉμ μμΉμμλΆν° Nκ°μ ν μ ν κ°λ₯
- FETCH FIRST μμ : SELECT EMPNO, ENAME, SAL FROM EMP ORDER BY SAL DESC FETCH FIRST 5 ROWS ONLY;
- OFFSET μμ : SELECT EMPNO, ENAME, SAL FROM EMP ORDER BY SAL DESC OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY; (μμ 5κ° ν 건λλ°κ³ , λ€μ 5κ° ν μ νν΄μ λ°ν)
μ°Έκ³
μ΄μ§ν¨μ€ 2025 SQLD SQL κ°λ°μ
β λΉ λ₯΄κ³ ν¨μ¨μ μΈ κ³΅λΆλ₯Ό μν SQLD μνμ λ°©λν SQL κ΄λ ¨ μ΄λ‘ μ SQLD μΆμ κ²½ν₯μ λ§μΆ° μκΈ° μ½κ² μ 리νμ¬ μκ°μ μ«κΈ°λ μνμλ€μ΄ μ΅λν κ³΅λΆ ν¨μ¨μ λμΌ μ μλλ‘ κ΅¬μ±νμ΅λλ€. β μ΄μ¬μ, λΉμ 곡μλ₯Ό μν΄ μ΄ν΄νκΈ° μ½κ² νμ΄ μ΄ SQLD μνμ SQLμ μ²μ μ νλ μ΄μ¬μλ λΉμ 곡μκ° μ΄ν΄νκΈ° μ½λλ‘ μμΈνκ² μ€λͺ
νμ΅λλ€. μμΈλ¬ μΆμ κ²½ν₯κ³Ό μ€μλλ₯Ό μλ΄νλ ‘TIP-BOX’, νλΆν μ€λͺ
μ λ΄μ ‘μ°Έκ³ -BOX’λ₯Ό νμ©νμ¬ μ΄ν΄νκΈ°
- μ μ
- μ μ©λ¬Έ
- μΆν
- μν€λΆμ€
- μΆνμΌ
- 2025.02.04
728x90