240612_TIL

J Lee·2024년 6월 12일
0

아무리 사소하더라도 배움이 없는 날은 없다.

SQL 코드카타 181번
181번~183번까지는 모두 Alternative Query에 관련된 문제다.
문제에서 따로 테이블을 정해주거나 뭘 쓰면 된다고 힌트를 준 것도 없어서, 임시로 CTE를 만들어서 푸는 방법밖에 없을 것 같다.

희한하게 여태까지는 CTE를 쓰면 오류가 났는데 이 문제에서는 CTE를 써도 정답으로 처리되었다_-

WITH RECURSIVE numbers AS (
    SELECT 20 AS n
    UNION ALL
    SELECT n - 1
    FROM numbers
    WHERE n > 1
)
SELECT REPEAT('* ', n)
FROM numbers;
  1. WITH RECURSIVE는 재귀적인 CTE를 만드는 쿼리다. RECURSIVE를 쓰면 CTE가 자신을 참조하게 된다.
  2. SELECT 20을 초기값 n으로 설정하고, n>1의 조건을 만족할 때까지 n을 하나씩 줄이면서 union한다. CTE의 재귀적인 성질로 인해 초기값 n과 그 다음에 생성된 n-1행이 합쳐지게 된다.
  3. 본 쿼리에서 REPEAT함수를 써서 별(*)을 n회 반복해 준다. n이 20부터 1까지 줄어들게끔 CTE에서 설정해 주었으므로, 별도 20부터 1까지 내림차순으로 찍히게 된다.

SQL 코드카타 182번

위의 문제에서 CTE의 로직만 바꿔주면 된다.

WITH RECURSIVE numbers AS (
    SELECT 1 AS n
    UNION ALL
    SELECT n + 1
    FROM numbers
    WHERE n < 20
)
SELECT REPEAT('* ', n)
FROM numbers;

CTE에 의해 n이 1부터 20까지 증가할 것이고,
본 쿼리에서 별(*)이 n만큼 반복(REPEAT)되면서 출력된다.

SQL 코드카타 183번
마지막은 1부터 1,000까지의 소수(prime number)를 &로 연결하면서 출력하는 쿼리를 짜는 문제. 예컨대 10까지의 소수 조합은

2&3&5&7

이런 형태로 출력되면 된다. 여기서도 CTE부터 정의한 후에 본 쿼리를 짜는 방식으로 접근해 보면,

WITH RECURSIVE numbers AS (
    SELECT 2 AS n
    UNION ALL
    SELECT n + 1
    FROM numbers
    WHERE n < 1000),

먼저 위 문제들과 똑같이 재귀적인 성질을 가진 CTE를 먼저 만들어 준다.
n은 가장 작은 소수인 2부터 시작해서 1,000에 도달할 때까지 1씩 증가하면서 합쳐지게 된다.

WITH RECURSIVE numbers AS (
    SELECT 2 AS n
    UNION ALL
    SELECT n + 1
    FROM numbers
    WHERE n < 1000
),
primes AS (
    SELECT n
    FROM numbers num
    WHERE NOT EXISTS (
        SELECT 1
        FROM numbers divisor
        WHERE divisor.n < num.n AND divisor.n > 1 AND num.n % divisor.n = 0
    )

이제 위에서 만든 number CTE를 참조해서 소수(prime) CTE를 만든다.

MySQL에서 소수는 1보다는 크고 n보다는 작은 어떤 수들(divisor.n)에 대하여, n이 그 수들로 나누어 떨어지는(num.n % divisor.n = 0) 경우가 없는(NOT EXIST조건) 조건을 만족하면 된다. 예를 들어 n이 5일 때는 1보다 크고 5보다는 작은 수 2,3,4에 대하여 5가 2,3,4로 나누었을 때 0이 되는 경우가 없으므로 5는 prime에 해당하는 식이다. 오히려 소수를 구현하는 조건은 파이썬보다 SQL이 더 간단한 것 같다.

마지막으로, prime CTE에 들어가 있는 소수들을 &로 연결하면서 불러오는 본 쿼리를 작성해 주면 정답이다.

WITH RECURSIVE numbers AS (
    SELECT 2 AS n
    UNION ALL
    SELECT n + 1
    FROM numbers
    WHERE n < 1000
),
primes AS (
    SELECT n
    FROM numbers num
    WHERE NOT EXISTS (
        SELECT 1
        FROM numbers divisor
        WHERE divisor.n < num.n AND divisor.n > 1 AND num.n % divisor.n = 0
    )
)
SELECT GROUP_CONCAT(n ORDER BY n SEPARATOR '&')
FROM primes;

GROUP_CONCAT은 예전 코드카타에서 한 번 썼던 적이 있는 함수인데 정말 오랜만에 다시 써 보게 됐다. n을 SEPARATOR '&'로 합쳐가면서 출력하고, 이 때 n의 순서는 오름차순에 의한다. (ORDER BY n) 만약 내림차순으로 출력하고 싶으면 ORDER BY n DESC로 적어주면 된다.

드디어 183번까지 모든 코드카타를 다 풀었다🥳
내일부터 아침 코드카타 시간은 리트코드나 다른 소스에서 문제를 더 구해서 풀거나, 이제까지 풀었던 코드카타에서 어려웠던 문제들만 다시 해결하면서 정리해 보는 시간으로 써야겠다.

profile
기본기를 소홀히 하지 말자

0개의 댓글

관련 채용 정보