[SQL] 해커랭크 : Print Prime Numbers (Stored Procedure, GROUP_CONCAT)

김시은·2022년 11월 23일
0

시작하며

문제 설명

👉🏻 해커랭크 Print Prime Numbers
1,000이하의 Prime Numbers(소수)를 찾아내는 문제이다.
결과는 & 를 구분자로 사용하여 2&3&5&7 형태로 출력해야 한다.

풀이 논리

  1. 1부터 1000까지의 숫자가 저장된 테이블을 생성한다.
  2. 1을 제외하고, 1000이하의 어떤 수의 배수가 되는 숫자는 모두 테이블에서 삭제한다. 1도 테이블에서 삭제한다.
  3. 해당 테이블의 데이터를 형식에 맞게 출력한다.

문제 풀이

1. 1 ~ 1000 숫자가 저장된 테이블 생성하기

빈 테이블 만들기

CREATE TABLE numbers (
	num INT PRIMARY KEY
);

CREATE 문으로 numbers 라는 테이블을 생성해준다.
테이블 안에는 num이라는 컬럼이 하나 들어있고, 해당 컬럼의 데이터타입은 INT라고 선언해준다.

WHILE문을 활용하여 테이블에 숫자 저장하기(Stored Procedure)

DELIMITER $$ -- ① 프로시저 생성을 위해 구분자 임시로 변경

CREATE PROCEDURE insertNum() -- ② insertNum 이라는 프로시저 생성
BEGIN
	DECLARE i INT DEFAULT 1; -- ③ 변수 i를 INT로 선언, 디폴트값으로 1 설정
    WHILE i <= 1000 DO -- ④ WHILE문 작성 (i가 1000이 될 때까지 아래 구문을 반복하라)
    	INSERT INTO numbers(num) VALUES (i); -- ⑤ 테이블에 i값 넣어주기
        SET i = i + 1; -- ⑥ i 값에 1 더해주고 WHILE문 처음으로 이동
    END WHILE;
END $$ -- ⑦ Prodedure 전체를 하나의 구문으로 마침

DELIMITER ; -- ⑧ DELIMITER를 다시 ;로 변경

insertNum이라는 프로시저를 만들어 테이블에 1부터 1000까지의 숫자를 넣어주었다.

① 프로시저 안에 여러 구문이 실행되기 때문에, 프로시저를 하나의 실행 단위로 구분해주기 위해 Delimiter를 $$로 변경해주었다. 👉🏻자세한 내용

Stored Procedure(저장 프로시저)란?

  • Stored Procedure는 반복해서 사용하는 쿼리를 하나의 루틴으로 저장하여 사용할 수 있게 한다.
  • Function과 비슷한 역할을 하지만, Function은 어떤 값을 리턴하지만 Procedure는 단순히 리턴값 없이 쿼리를 콜한다는 점에서 다르다.
  • Procedure 내에 기본 SELECT 문 뿐만 아니라 IF, CASE, WHILE 등 다양한 구문을 활용할 수 있다.

프로시저 실행하기

CALL insertNum();

생성한 프로시저는 CALL로 실행할 수 있다.

2. 소수가 아닌 숫자를 테이블에서 삭제하기

소수가 아닌 숫자를 삭제하는 프로시저 생성하기

DELIMITER $$

CREATE PROCEDURE deleteNonPrime()
BEGIN 
	DECLARE i INT DEFAULT 2;
    WHILE i <= 1000 DO
      DELETE FROM numbers WHERE (num % i = 0) AND (num / i > 1); -- ① 소수가 아닌 숫자는 삭제
      SET i = i + 1;
    END WHILE;
    DELETE FROM numbers WHERE num = 1; -- ② 숫자 1 삭제
END $$

DELIMITER ;

소수는 1과 나 자신 외의 수로 나누어지지 않는 수를 말한다.
① 소수가 아닌 숫자는 즉, 2부터 1000까지의 숫자 중 어떤 숫자의 배수이고 (num % i = 0) 몫이 1보다 큰 (num / i > 1) 숫자이다.
몫이 1보다 큰 것을 조건으로 둔 이유는, 이 조건이 없다면 소수가 자기 자신으로 나눠져 나머지가 0이 되어 삭제되기 때문이다. (예를 들어, i = 2 일 때, 2/2 = 1로 소수임에도 삭제 대상이 된다.
WHILE 문을 통해 2부터 1000까지의 모든 수로 테이블의 숫자가 나누어지는지 확인하여 결과적으로 소수만 남게 된다.

② 숫자 1은 특수한 경우로 따로 삭제해준다.

프로시저 실행하기

CALL deleteNonPrime();

프로시저를 실행하면 numbers 테이블에는 소수만 남게 된다.

조건에 맞게 결과를 출력하기

GROUP_CONCAT

GROUP_CONCAT은 서로 다른 행에 있는 데이터를 한 줄로 합쳐줄 때 사용한다.

SELECT GROUP_CONCAT([컬럼명] separator [구분자] | ORDER BY [컬럼명])
FROM [테이블명]
GROUP BY [그룹명]

GROUP BY 문을 포함하면, 그룹별로 묶어서 해당하는 데이터를 한 줄로 출력해준다.
GROUP BY 문을 포함하지 않으면, 모든 데이터를 하나의 그룹으로 보고 한 줄로 출력해준다.
ORDER BY 문을 사용하면 특정 컬럼을 기준으로 정렬하여 출력할 수 있다.

GROUP_CONCAT 적용하기

SELECT GROUP_CONCAT(num separator '&')
FROM numbers;

최종 쿼리 및 결과

CREATE TABLE numbers (
    num INT PRIMARY KEY
);

DELIMITER $$

CREATE PROCEDURE insertNum()
BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE i <= 1000 DO 
        INSERT INTO numbers(num) VALUES (i);
        SET i = i + 1;
    END WHILE;
END $$

DELIMITER ;

CALL insertNum();

DELIMITER $$

CREATE PROCEDURE deleteNonPrime()
BEGIN 
    DECLARE i INT DEFAULT 2;
    WHILE i <= 1000 DO
        DELETE FROM numbers WHERE (num % i = 0) AND (num / i > 1);
        SET i = i + 1;
    END WHILE;
    DELETE FROM numbers WHERE num = 1;
END $$

DELIMITER ;

CALL deleteNonPrime();

SELECT GROUP_CONCAT(num separator '&')
FROM numbers;

문제에서 제시된 조건대로 모든 소수들이 출력되었다.

참고자료

Procedure 관련

profile
데이터분석가를 꿈꾸어요

0개의 댓글