HackerRank: SQL 풀이 58

SeongGyun Hong·2024년 12월 26일

SQL

목록 보기
22/51

58. Alternative Queries: Print Prime Numbers

이건 진짜 그냥 몰라서 어캐 푸는지 처음부터 봤음
처음 보는 유형 + 처음 보는 함수가 너무 많아서 아래에서 서술하도록 하겠음

  • 정답 쿼리
DECLARE @max INT = 1000;

WITH Numbers AS (
    SELECT 2 AS Num
    UNION ALL
    SELECT Num + 1
    FROM Numbers
    WHERE Num + 1 <= @max
),
Primes AS (
    SELECT Num
    FROM Numbers N
    WHERE NOT EXISTS (
        SELECT 1
        FROM Numbers D
        WHERE D.Num < N.num AND N.Num % d.Num = 0
    )
)
SELECT STRING_AGG(CAST(Num AS VarCHAR), '&') AS PrimeNumbers
FROM Primes
OPTION (MAXRECURSION 1000);

Step 1: DECLARE @max INT = 50;

  • DECLARE: SQL에서 변수를 선언할 때 사용하는 키워드

  • @max: 변수 이름
    변수 이름 앞에는 @를 붙여 SQL에서 변수를 나타냄

  • INT: 이 변수의 데이터 타입으로, 정수(Integer)를 의미

  • = 50: 변수에 초기값을 설정
    여기서는 @max의 값을 50으로 설정

이 줄의 의미:

  • "최대 숫자를 1000으로 설정한다"

Step 2: WITH Numbers AS (...)

  • WITH: CTE(Common Table Expression)를 정의할 때 사용하는 키워드
  • Numbers: 이 CTE의 이름
    "Numbers"라는 이름을 가진 임시 테이블을 생성
  • AS (...): 이 이름(Numbers)을 정의할 때 실행할 쿼리를 괄호 안에 넣는다.

Step 2.1: SELECT 2 AS Num

  • SELECT: 데이터를 선택하는 SQL 키워드
  • 2: 고정된 값 2를 생성
  • AS Num: 이 값에 "Num"이라는 이름(별칭)을 붙인다.

이 줄의 역할:

  • CTE에 첫 번째 숫자(2)를 삽입
  • 별도의 FROM 절 불필요
    (고정값을 생성하는 SELECT 쿼리에서는 FROM이 생략 가능하기 때문)
  • 결과:
    Num
    ---
    2

Step 2.2: UNION ALL SELECT Num + 1 FROM Numbers WHERE Num + 1 <= @max

  • UNION ALL: 두 개의 결과를 결합
    중복된 값도 포함
  • SELECT Num + 1: 기존 숫자(Num)에 1을 더한 값을 생성
  • FROM Numbers: 앞에서 정의된 Numbers CTE를 참조
  • WHERE Num + 1 <= @max: 새로 생성된 숫자가 @max(50) 이하인지 확인하고 조건을 만족하지 않으면 값을 추가하지 않음.

재귀적으로 동작하는 과정:

  1. 처음에는 SELECT 2 AS Num 실행 → Numbers 테이블에 2가 저장됨
    Num
    ---
    2
  2. 재귀 쿼리가 실행:
    • SELECT Num + 1 FROM Numbers WHERE Num + 1 <= @max
    • Num2일 때: 2 + 1 = 3
    • 결과:
      Num
      ---
      2
      3
  3. 다시 실행:
    • Num3일 때: 3 + 1 = 4
    • 결과:
      Num
      ---
      2
      3
      4
  4. 이렇게 Num 값이 1000이 될 때까지 반복.

Step 3: WITH Primes AS (...)

  • Numbers CTE를 기반으로 소수를 필터링하는 또 다른 CTE를 만듦

Step 3.1: SELECT Num FROM Numbers n

  • SELECT Num: Numbers CTE에서 Num 값을 가져오고
  • FROM Numbers n: Numbers CTE를 n이라는 별칭으로 참조

Step 3.2: WHERE NOT EXISTS (...)

  • NOT EXISTS: 조건에 맞는 결과가 존재하지 않을 때만 true를 반환
안쪽 쿼리:
SELECT 1
FROM Numbers d
WHERE d.Num < n.Num AND n.Num % d.Num = 0
  • SELECT 1: 특정 값을 반환
    여기서는 1만 반환
  • FROM Numbers d: Numbers CTE를 d라는 별칭으로 참조
  • WHERE d.Num < n.Num: d.Numn.Num보다 작은 숫자만 찾음.
  • AND n.Num % d.Num = 0: n.Numd.Num으로 나누어떨어지는 숫자만 선택
의미:
  • 숫자 n.Num보다 작은 숫자 중, n.Num을 나누어떨어지게 하는 숫자가 존재하면, n.Num은 소수가 아님.
  • NOT EXISTS: 위 조건을 만족하는 숫자가 존재하지 않을 때만 n.Num을 소수로 간주

Step 4: SELECT STRING_AGG(CAST(Num AS VARCHAR), '&') AS PrimeNumbers FROM Primes

  • SELECT STRING_AGG(...): SQL Server의 함수로, 여러 값을 하나의 문자열로 결합
  • CAST(Num AS VARCHAR): 숫자 Num을 문자열로 변환
  • '&': 값들을 결합할 때 사용하는 구분자
  • FROM Primes: 소수(Primes CTE)에서 값을 가져옴

최종 실행 결과

  • 예를 들어, @max = 50이라면 Primes CTE에는 다음 소수가 저장
    Num
    ---
    2
    3
    5
    7
    11
    13
    ...
  • 최종 출력:
    2&3&5&7&11&13&17&19&23&29&31&37&41&43&47

요약

  1. DECLARE: 최대값(@max)을 설정
  2. WITH Numbers: 2부터 @max까지의 숫자를 생성
  3. WITH Primes: Numbers에서 소수만 필터링
  4. SELECT STRING_AGG: 소수들을 &로 연결된 문자열로 출력
profile
헤매는 만큼 자기 땅이다.

0개의 댓글