본문 바로가기

SQL/HackerRank (SQL문풀)

HackerRank / Alternative Queries / Print Prime Numbers / MySQL

728x90

📚문제

출처 : Hackerrank(https://www.hackerrank.com/challenges/print-prime-numbers/problem?isFullScreen=true)


📝풀이

SELECT GROUP_CONCAT(NUMB SEPARATOR '&')
FROM (
    SELECT @num:=@num+1 as NUMB FROM
    information_schema.tables t1,
    information_schema.tables t2,
    (SELECT @num:=1) tmp
) tempNum
WHERE NUMB<=1000 AND NOT EXISTS(
		SELECT * FROM (
			SELECT @nu:=@nu+1 as NUMA FROM
			    information_schema.tables t1,
			    information_schema.tables t2,
			    (SELECT @nu:=1) tmp1
			    LIMIT 1000
			) tempNum1
		WHERE FLOOR(NUMB/NUMA)=(NUMB/NUMA) AND NUMA<NUMB AND NUMA>1)

테이블 없이 풀라고하는 문제는 처음이라 당황했다..

구글링하여 풀이를 참고했는데 

세분화해서 부분별/단계별로 확인

 


1단계

SELECT *
FROM (
    SELECT @num:=@num+1 as NUMB FROM
    information_schema.tables t1,
    information_schema.tables t2,
    (SELECT @num:=1) tmp ) tempNum

information_schema라는 것은 

MySQL 서버 내에 존재하는 DB의 메타정보(테이블,칼럼,인덱스 등의 스키마 정보)라고 한다

간단하게

애초에 MySQL에 존재하는 테이블을 사용한다는 것 같다

 

테이블을 2개나 사용하는 이유는 

1개의테이블은 1000개의 행이 되지 않기 때문에

2개의 테이블을 Cross Join한 다음에

LIMIT로 1000행을 제안하기 위해서이다

 

그리고 여기서 

(SELECT @num:=1)

이 쿼리는 

서브쿼리이면서

변수 @num에 초기값을 할당하는 역할을 한다

 

MySQL Workbench에서 실행하면 다음과 같이 나온다

이 때 변수의 초기값을 설정해주지 않으면 

Hackerrank에서는 전부 NULL값으로 나온다

 

 


2단계

WHERE NUMB<=1000

행의 수가 1000개가 넘어가므로 개수를 1000개로 제한한다

 

NOT EXISTS(
		SELECT * FROM (
			SELECT @nu:=@nu+1 as NUMA FROM
			    information_schema.tables t1,
			    information_schema.tables t2,
			    (SELECT @nu:=1) tmp1
			    LIMIT 1000
			) tempNum1
		WHERE FLOOR(NUMB/NUMA)=(NUMB/NUMA) AND NUMA<NUMB AND NUMA>1)

그 다음 다른 WHERE조건과 NOT EXISTS 조건으로 필터링

 

동일한 테이블을 한개 더 생성한 다음

그 테이블의 조건을 걸어주는데 이 조건을 보면

WHERE FLOOR(NUMB/NUMA)=(NUMB/NUMA) AND NUMA<NUMB AND NUMA>1

 

FLOOR(NUMB/NUMA) == NUMB / NUMA 이라면 소수가 아니다

 

라는 뜻

그래서 NOT EXISTS를 걸어서 조건에 해당하지 않는 행들만 가져옴

 

💡이 때 NOT IN 이 아닌 NOT EXISTS를 사용하는 이유

출처 : https://notmoonsong.tistory.com/28

 

그리고 NUMB(피제수)가 NUMA(제수)보다 커야한다는 조건과

NUMA(제수)가 1보다 커야한다는 조건을 지켜주어야 한다

( 소수는 1과 자기자신을 제외하기 때문에 =>  1 < NUMA < NUMB 라는 얘기)

 

 


3단계

SELECT GROUP_CONCAT(NUMB SEPARATOR '&')
FROM (
    SELECT @num:=@num+1 as NUMB FROM
    information_schema.tables t1,
    information_schema.tables t2,
    (SELECT @num:=1) tmp
) tempNum
WHERE NUMB<=1000 AND NOT EXISTS(
		SELECT * FROM (
			SELECT @nu:=@nu+1 as NUMA FROM
			    information_schema.tables t1,
			    information_schema.tables t2,
			    (SELECT @nu:=1) tmp1
			    LIMIT 1000
			) tempNum1
		WHERE FLOOR(NUMB/NUMA)=(NUMB/NUMA) AND NUMA<NUMB AND NUMA>1)

나온 결과를

GROUP_CONCAT()함수로 처리하기

NUMB 열의 모든 값을 

한줄로 출력하는데 이때 '&'연산자를 가지고 묶어준다

 

+ GROUP_CONCAT의 사용법

출처 : https://notmoonsong.tistory.com/28

 

 

 

+ 풀이 참고 링크

출처: https://techblog-history-younghunjo1.tistory.com/173

 

728x90