1. 없어진 기록 찾기 - LEFT OUTER JOIN

천재지변으로 인해 일부 데이터가 유실되었습니다. 입양을 간 기록은 있는데, 보호소에 들어온 기록이 없는 동물의 ID와 이름을 ID 순으로 조회하는 SQL문을 작성해주세요.

SELECT O.ANIMAL_ID, O.NAME
FROM ANIMAL_OUTS O LEFT OUTER JOIN ANIMAL_INS I ON O.ANIMAL_ID = I.ANIMAL_ID
WHERE I.ANIMAL_ID IS NULL
ORDER BY O.ANIMAL_ID

 

2. 있었는데요 없었습니다 - LEFT OUTER JOIN

관리자의 실수로 일부 동물의 입양일이 잘못 입력되었습니다. 보호 시작일보다 입양일이 더 빠른 동물의 아이디와 이름을 조회하는 SQL문을 작성해주세요. 이때 결과는 보호 시작일이 빠른 순으로 조회해야합니다.

SELECT I.ANIMAL_ID, I.NAME
FROM ANIMAL_INS I LEFT OUTER JOIN ANIMAL_OUTS O ON I.ANIMAL_ID = O.ANIMAL_ID
WHERE I.DATETIME>O.DATETIME
ORDER BY I.DATETIME

 

3. 오랜시간 보호한 동물(1) - LEFT OUTER JOIN

아직 입양을 못 간 동물 중, 가장 오래 보호소에 있었던 동물 3마리의 이름과 보호 시작일을 조회하는 SQL문을 작성해주세요. 이때 결과는 보호 시작일 순으로 조회해야 합니다.

SELECT I.NAME, I.DATETIME
FROM ANIMAL_INS I LEFT OUTER JOIN ANIMAL_OUTS O ON I.ANIMAL_ID = O.ANIMAL_ID
WHERE O.ANIMAL_ID IS NULL
ORDER BY I.DATETIME LIMIT 3

 

4. 보호소에서 중성화한 동물 - LEFT OUTER JOIN

보호소에서 중성화 수술을 거친 동물 정보를 알아보려 합니다. 보호소에 들어올 당시에는 중성화되지 않았지만, 보호소를 나갈 당시에는 중성화된 동물의 아이디와 생물 종, 이름을 조회하는 아이디 순으로 조회하는 SQL 문을 작성해주세요.

SELECT O.ANIMAL_ID, O.ANIMAL_TYPE, O.NAME
FROM ANIMAL_OUTS O LEFT OUTER JOIN ANIMAL_INS I ON O.ANIMAL_ID = I.ANIMAL_ID
WHERE I.SEX_UPON_INTAKE != O.SEX_UPON_OUTCOME 
ORDER BY O.ANIMAL_ID

 

1. 이름이 없는 동물의 아이디 -> IS NULL

동물 보호소에 들어온 동물 중, 이름이 없는 채로 들어온 동물의 ID를 조회하는 SQL 문을 작성해주세요. 단, ID는 오름차순 정렬되어야 합니다.

SELECT ANIMAL_ID
FROM ANIMAL_INS
WHERE NAME IS NULL
ORDER BY ANIMAL_ID

조건 : 이름이 없는 채로 들어온 동물의 ID -> WHERE NAME IS NULL

" == NULL " 의 형태는 쓸 수 없다 

 

2. 이름이 있는 동물의 아이디 -> IS NOT NULL

동물 보호소에 들어온 동물 중, 이름이 있는 동물의 ID를 조회하는 SQL 문을 작성해주세요. 단, ID는 오름차순 정렬되어야 합니다.

SELECT ANIMAL_ID
FROM ANIMAL_INS
WHERE NAME IS NOT NULL
ORDER BY ANIMAL_ID

조건 : 이름이 없는 채로 들어온 동물의 ID -> WHERE NAME IS NOT NULL

 

3. NULL 처리하기 -> IFNULL

입양 게시판에 동물 정보를 게시하려 합니다. 동물의 생물 종, 이름, 성별 및 중성화 여부를 아이디 순으로 조회하는 SQL문을 작성해주세요. 이때 프로그래밍을 모르는 사람들은 NULL이라는 기호를 모르기 때문에, 이름이 없는 동물의 이름은 "No name"으로 표시해 주세요.

SELECT ANIMAL_TYPE, IFNULL(NAME,"No name") AS NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
ORDER BY ANIMAL_ID

ANIMAL_TYPE, NAME, SEX_UPON_INTAKE 조회

여기서 NAME은 NULL일 때, "No name" , NULL이 아닐 때 NAME으로 분류된다.

이때 사용하는 함수는 " IFNULL"

 

cf) IFNULL vs NULLIF 

  • IFNULL(A, B) : A가 NULL이면 B리턴, A가 NULL이 아니면 A를 리턴
  • NULLIF(A,B) : A==B이면 NULL 리턴, A!=B이면 A 리턴

 

 ** ORACLE의 경우, 더 많은 함수를 쓸 수 있다!

 

NVL, NVL2, DECODE

  • NVL(A,B) : A가 NULL이면 B 리턴, A가 NULL이 아니면 A를 리턴 (MySQL의 IFNULL과 동일)
  • NVL2(A,NULL이 아닐경우 값,NULL일 경우의 값) : A,  A가 NULL이 아닐 경우와 A가 NULL일 경우
  • DECODE(A,IF_1, THEN_1, IF_2, THEN2, ...,default값) : 우리가아는 case문이랑 비슷, A가 IF_1이면 THEN_1, IF_2면 THEN_2 ... 없으면 default값 리턴
--NVL 사용
SELECT ANIMAL_TYPE, NVL(NAME,'No name') AS NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

--NVL2 사용
SELECT ANIMAL_TYPE, NVL2(NAME,NAME,'No name') AS NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

--DECODE 사용
SELECT ANIMAL_TYPE, DECODE(NAME, NULL,'No name',NAME) AS NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

 

4. 입양 시각 구하기 (2)

보호소에서는 몇 시에 입양이 가장 활발하게 일어나는지 알아보려 합니다. 0시부터 23시까지, 각 시간대별로 입양이 몇 건이나 발생했는지 조회하는 SQL문을 작성해주세요. 이때 결과는 시간대 순으로 정렬해야 합니다.

 

첨엔 GROUP BY로 해결하려 했으나 COUNT가 0인 부분에 대해서 조회할 수 없어서 실패 

두번째 시도는 UNION ALL 이었는데,,,, (sol 2) 같이 일일히 다 써야하기 때문에 패스! 

(sol 1) SET, @변수 사용 

SET @HOUR := -1;
SELECT (@HOUR := @HOUR+1) AS HOUR, (SELECT COUNT(*) 
                                    FROM ANIMAL_OUTS
                                    WHERE HOUR(DATETIME) = @HOUR) AS COUNT
FROM ANIMAL_OUTS
WHERE @HOUR < 23

 

1. "SET" 사용 : 변수 선언 (어떤 변수에 특정 값을 할당 하는 것을 말함)

- 변수 앞에 @ 지정 : 프로시저가 종료되어도 유지됨 , 따라서 값 누적이 가능

 - " = ", " := "에 따라 의미가 달라진다 

  • " = " : 대입연산자, 비교연산자 
  • " := " : 대입연산자로만 사용,
  • = 는 대입연산자로도 쓸 수 있지만, 비교연산자와의 혼동을 막기위해 := 주로 사용

따라서, HOUR라는 변수를 프로시저가 종료되어도 유지되도록 설정하고, -1로 초기화 -> SET @HOUR := -1; 

 

※ 왜 -1 인가? 

SELECT 문에서 (@HOUR := @HOUR +1) AS HOUR 로 지정하는데, 이 식 때문에 -1+1 = 0 부터 시작하게 된다! 

 

2.  HOUR가 0~23까지 1씩 증가해야하므로 (@HOUR := @HOUR +1) 로 지정해주고 alias 사용하여 HOUR 칼럼명 지정

COUNT의 경우는, HOUR(DATETIME)과 @HOUR변수의 값이 동일할 때의 개수를 세어주면 되므로 아래와 같다

(SELECT COUNT(*) FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = @HOUR) AS COUNT

 

3. FROM ANIMAL_OUTS(테이블 선정)

 

4. WHERE @HOUR<23 : @HOUR가 23이 될때까지

(sol 2) UNION ALL 사용

SELECT HOUR, COUNT
FROM(
    SELECT 0 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 0
    UNION ALL
    SELECT 1 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 1
    UNION ALL
    SELECT 2 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 2
    UNION ALL
    SELECT 3 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 3
    UNION ALL
    SELECT 4 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 4
    UNION ALL
    SELECT 5 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 5
    UNION ALL
    SELECT 6 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 6
    UNION ALL
    SELECT 7 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 7
    UNION ALL
    SELECT 8 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 8
    UNION ALL
    SELECT 9 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 9
    UNION ALL
    SELECT 10 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 10
    UNION ALL
    SELECT 11 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 11
    UNION ALL
    SELECT 12 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 12
    UNION ALL
    SELECT 13 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 13
    UNION ALL
    SELECT 14 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 14
    UNION ALL
    SELECT 15 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 15
    UNION ALL
    SELECT 16 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 16
    UNION ALL
    SELECT 17 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 17
    UNION ALL
    SELECT 18 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 18
    UNION ALL
    SELECT 19 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 19
    UNION ALL
    SELECT 20 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 20
    UNION ALL
    SELECT 21 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 21
    UNION ALL
    SELECT 22 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 22
    UNION ALL
    SELECT 23 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 23
    UNION ALL
    SELECT 24 AS HOUR, COUNT(*) AS COUNT FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = 24
    ) AS t
WHERE HOUR >= 0 AND HOUR <= 23
ORDER BY HOUR

 

참고로, UNION ALL 과 UNION의 차이

UNION ALL은 중복을 제거하지 않고 모두! (합집합+교집합)

UNION은 중복을 제거한상태로 합치는 것! (합집합)

3. 입양시각 구하기 - HOUR로 시간 추출

보호소에서는 몇 시에 입양이 가장 활발하게 일어나는지 알아보려 합니다. 09:00부터 19:59까지, 각 시간대별로 입양이 몇 건이나 발생했는지 조회하는 SQL문을 작성해주세요. 이때 결과는 시간대 순으로 정렬해야 합니다.

(sol 1) HAVING절 사용! 

SELECT HOUR(DATETIME) AS HOUR, COUNT(DATETIME) AS COUNT
FROM ANIMAL_OUTS
GROUP BY HOUR
HAVING HOUR>=9 AND HOUR<20
ORDER BY HOUR

1. HOUR(DATETIME)를 사용하면 "2021.12.18 13:07:12" 로 되어있는 datetime(날짜+시간) format에서 Hour에 해당하는 "13"만 뽑아 낼 수 있다!

따라서  HOUR(DATETIME)과 COUNT(DATETIME)의 각 컬럼명을 HOUR, COUNT로 조회!

SELECT HOUR(DATETIME) AS HOUR, COUNT(DATETIME) AS COUNT

 

2. FROM ANIMAL_OUTS(테이블 선택)

 

3.  HOUR 에 따라 그룹화 -> GROUP BY HOUR

여기서 HOUR(DATETIME)해도 되고 HOUR만 해도 된다! -> select절에서 HOUR(DATETIME)을 HOUR로 정의해주었기 때문! 

 

4. 그룹화한 후, 조건을 걸어준다 9시이후 20시미만. -> HAVING HOUR>=9 AND HOUR<20

조건이 2개이므로 AND로 연결해주면 된다

 

5. 마지막으로 HOUR에 따라 정렬 -> ORDER BY HOUR

 

(sol 2) WHERE 절 사용! 

참고로 HAVING 과 WHERE 의 차이는( https://bskwak.tistory.com/234 ) 여기서 확인할 수 있다!

SELECT HOUR(DATETIME) AS HOUR, COUNT(DATETIME) AS COUNT
FROM ANIMAL_OUTS
WHERE HOUR(DATETIME)>=9 AND HOUR(DATETIME)<20
GROUP BY HOUR
ORDER BY HOUR

1. (sol 1)과 동일하게  HOUR(DATETIME)를 사용

SELECT HOUR(DATETIME) AS HOUR, COUNT(DATETIME) AS COUNT

 

2. FROM ANIMAL_OUTS(테이블 선택)

 

3. 그룹화 하기 전에, 미리 조건을 걸어준다! 

WHERE HOUR(DATETIME) >= 9 AND HOUR(DATETIME)<20

** 여기서는 HOUR(DATETIME)을 꼭! 써주어야 한다! HOUR로만 쓰게 되면,

"Unknown column 'HOUR' in 'where clause' " 라는 에러 발생 

꼭 WHERE 절에 HOUR(SELECT 에서 alias 사용한 단어)로 쓰고싶다면, -> (sol 3) 참고 

 

4.  HOUR 에 따라 그룹화 -> GROUP BY HOUR

여기서 HOUR(DATETIME)해도 되고 HOUR만 해도 된다! -> select절에서 HOUR(DATETIME)을 HOUR로 정의해주었기 때문! 

 

5. 마지막으로 HOUR에 따라 정렬 -> ORDER BY HOUR

 

(sol 3) WHERE 절에 alias 사용

SELECT *
FROM (SELECT HOUR(DATETIME) AS HOUR, COUNT(DATETIME) AS COUNT
      FROM ANIMAL_OUTS
      GROUP BY HOUR
      ORDER BY HOUR) AS t
WHERE HOUR>=9 AND HOUR<20

 

즉, 하나의 질의문을 FROM절에 넣을 서브쿼리로 작성한 후에 감싸고 있는 query에서 SELECT절에서 서브쿼리의 alias를 사용하여주면,  WHERE절에서 해당 alias 단어 사용 가능

(서브 쿼리문) HOUR로 그룹화하고 정렬한 테이블 중 HOUR와 COUNT 컬럼으로 조회한 테이블 -> t alias 사용하여 지정

1. 고양이와 개는 몇 마리 있을까 - GROUP BY

동물 보호소에 들어온 동물 중 고양이와 개가 각각 몇 마리인지 조회하는 SQL문을 작성해주세요. 이때 고양이를 개보다 먼저 조회해주세요.

SELECT ANIMAL_TYPE, COUNT(ANIMAL_TYPE) AS count
FROM ANIMAL_INS
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE

1. SELECT ANIMAL_TYPE, count 인데, count라는 컬럼이 없으므로 어떤 식 AS count 가 되어야 한다.

즉, 어떤 식의 결과값을 count로 정의!

ANIMAL_TYPE 별 개수를 구하는 것이므로 COUNT(ANIMAL_TYPE) AS count

 

2. FROM ANIMAL_INS(테이블명)

 

3. GROUP BY ** 이 문제의 핵심!

* GROUP BY : 특정 컬럼을 그룹화하여 데이터 조회!

GROUP BY 특정컬럼명

말 그대로 특정컬럼을 그룹화 한다는 의미인데, 

그룹화를 하면 조회된 데이터를 통계를 내기 위한 집계함수( avg, sum,...)를 사용하기 쉬워진다!

GROUP BY ANIMAL_TYPE == ANIMAL_TYPE으로 그룹화 == cat끼리, dog끼리 그룹

 

4. ORDER BY ANIMAL_TYPE : Cat 먼저 조회해야하므로, ORDER BY (ASC) 사용 ( C < D)

 

 

2. 동명 동물 수 찾기

동물 보호소에 들어온 동물 이름 중 두 번 이상 쓰인 이름과 해당 이름이 쓰인 횟수를 조회하는 SQL문을 작성해주세요. 이때 결과는 이름이 없는 동물은 집계에서 제외하며, 결과는 이름 순으로 조회해주세요.

SELECT NAME, COUNT(NAME) AS COUNT
FROM ANIMAL_INS
WHERE NAME IS NOT NULL
GROUP BY NAME
HAVING COUNT > 1
ORDER BY NAME

1.  SELECT  NAME, COUNT 인데, COUNT 라는 컬럼이 없으므로 어떤 식 AS COUNT 가 되어야 한다.

즉, 어떤 식의 결과값을 count로 정의!

NAME별 개수를 구하는 것이므로 COUNT(NAME) AS COUNT

 

2. FROM ANIMAL_INS(테이블명)

 

3. ** GROUP BY를 쓸 때 WHERE과 HAVING의 사용에 주의해야한다! ** 이 문제의 핵심!!

 

참고로, mysql 문법 작성순서는 다음과 같다

SELECT 컬럼명
FROM 테이블명
WHERE 조건식
GROUP BY 칼럼명
HAVING 조건식
ORDER BY 칼럼명

하지만, 실행작동순서는 작성 순서와 다르다!!

위의 경우로만 보면,

FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY

 

여기서 WHERE 과 HAVING 의 차이가 드러난다

WHERE : 그룹화하기 전의 조건

HAVING : 그룹화 후의 조건

 

따라서, 문제를 보면,

이름이 없는 동물은 집계에서 제외

-> 집계(GROUP BY)를 하기 전에 미리 걸러주어라! 하는 의미이므로

WHERE NAME IS NOT NULL 을 사용

 

동물 이름 중 두 번 이상 쓰인 이름과 해당 이름이 쓰인 횟수를 조회

동물 이름으로 GROUP 화를 먼저 한 후에  (GROUP BY NAME)

"두번 이상" 이라는 조건을 걸어주면 된다! 

따라서 HAVING COUNT > 1  을 사용

 

4. 마지막으로 결과는 이름순으로 조회하라 했으므로,

ORDER BY NAME

 

 

 

 

1. 최댓값구하기

가장 최근에 들어온 동물은 언제 들어왔는지 조회하는 SQL 문을 작성해주세요.

 

sol (1) ORDER BY를 사용

SELECT DATETIME
FROM ANIMAL_INS
ORDER BY DATETIME DESC LIMIT 1

<SELECT문>에서 풀었듯이,

DATETIME을 내림차순으로 정렬하면 가장 최근 날짜가 가장 위에 오게 됨

따라서, "LIMIT 1"을 사용함으로써 하나!만 

 

sol (2) MAX 함수 사용 

SELECT MAX(DATETIME)
FROM ANIMAL_INS

최댓값 : SELECT MAX(컬럼) FROM 테이블

참고로, AS(Alias)를 이용하여 컬럼명 정의할 수 있음

ex) SELECT MAX(DATETIME) AS date FROM ANIMAL_INS 라 쓰면, 출력할 컬럼의 명을 date로 지정한다는 의미!

 

2. 최솟값 구하기

동물 보호소에 가장 먼저 들어온 동물은 언제 들어왔는지 조회하는 SQL 문을 작성해주세요.

 

sol (1) ORDER BY를 사용

SELECT DATETIME
FROM ANIMAL_INS
ORDER BY DATETIME LIMIT 1

DATETIME을 ORDER BY해주면, 기본 설정이 오름차순이므로 오름차순 정렬

따라서 가장 먼저 들어온 날짜(맨 처음 날짜)가 맨 위에 오게 된다!

따라서 LIMIT 1 을 사용함으로써 하나!만

 

sol (2) MAX 함수 사용 

SELECT MIN(DATETIME)
FROM ANIMAL_INS

최소값 : SELECT MIN(컬럼) FROM 테이블

 

3. 동물 수 구하기 => 집계함수 (COUNT)

동물 보호소에 동물이 몇 마리 들어왔는지 조회하는 SQL 문을 작성해주세요.

SELECT COUNT
FROM ANIMAL_INS

수를 세는 함수 : COUNT

 

4. 중복 제거하기 - DISTINCT

동물 보호소에 들어온 동물의 이름은 몇 개인지 조회하는 SQL 문을 작성해주세요. 이때 이름이 NULL인 경우는 집계하지 않으며 중복되는 이름은 하나로 칩니다.

SELECT COUNT(DISTINCT NAME)
FROM ANIMAL_INS
WHERE NAME IS NOT NULL

몇 개인지? => COUNT

중복된 이름은 하나로 친다 == 중복 제거 => DISTINCT 함수 사용

  • DISTINCT 칼럼명 : 해당 칼럼에서 중복된 값 제거 

NAME이 NULL인 경우는 집계하지 않으므로, 조건문 사용

1. 모든 레코드 조회하기 

동물 보호소에 들어온 모든 동물의 정보를 ANIMAL_ID순으로 조회하는 SQL문을 작성해주세요. 

SELECT *
FROM ANIMAL_INS
ORDER BY ANIMAL_ID

SELECT(조회) * (모든 정보)

FROM ANIMAL_INS (ANIMAL_INS 테이블에서)

ORDER BY ANIMAL_ID ( ANIMAL_ID를 오름차순으로 정렬)

 

Order by는 "ASC" (오름차순)이 기본적으로 설정되어 있어서 굳이 작성하지 않아도 된다

 

2. 역순 정렬하기

동물 보호소에 들어온 모든 동물의 이름과 보호 시작일을 조회하는 SQL문을 작성해주세요. 이때 결과는 ANIMAL_ID 역순으로 보여주세요. 

SELECT NAME, DATETIME
FROM ANIMAL_INS
ORDER BY ANIMAL_ID DESC

SELECT 옆에는 조회하고자하는 컬럼 이름을 작성해주면 된다. 

 

"역순"으로 정렬 이므로, DESC를 사용!

 

3. 아픈 동물 찾기 - 조건문

동물 보호소에 들어온 동물 중 아픈 동물의 아이디와 이름을 조회하는 SQL 문을 작성해주세요. 이때 결과는 아이디 순으로 조회해주세요.

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE INTAKE_CONDITION = "Sick"
ORDER BY ANIMAL_ID

아픈 동물을 조회해야하므로 "조건문"을 사용해야한다

조건문 : WHERE 조건

이때, 아픈 동물은 INTAKE_CONDITION이 "Sick"인 경우이므로 위와 같은 코드가 완성된다!

 

더보기

아픈동물이 "Normal이 아닌 경우" 인줄 알고 계속 제출했다가 엄청 틀렸다

다음부턴 문제를 잘 읽어야겠다..

 

4. 어린 동물 찾기 - 조건문

동물 보호소에 들어온 동물 중 젊은 동물의 아이디와 이름을 조회하는 SQL 문을 작성해주세요. 이때 결과는 아이디 순으로 조회해주세요.

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE INTAKE_CONDITION != "Aged"
ORDER BY ANIMAL_ID

젊은 동물은 INTAKE_CONDITION이 "Aged"가 아닌경우이므로, 조건문에 위와 같이 작성

 

5. 동물 아이디와 이름

동물 보호소에 들어온 모든 동물의 아이디와 이름을 ANIMAL_ID순으로 조회하는 SQL문을 작성해주세요. 

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
ORDER BY ANIMAL_ID

 

6. 여러 기준으로 정렬하기 

동물 보호소에 들어온 모든 동물의 아이디와 이름, 보호 시작일을 이름 순으로 조회하는 SQL문을 작성해주세요. 단, 이름이 같은 동물 중에서는 보호를 나중에 시작한 동물을 먼저 보여줘야 합니다.

SELECT ANIMAL_ID,NAME,DATETIME
FROM ANIMAL_INS
ORDER BY NAME ASC, DATETIME DESC

 

" ORDER BY A (ASC/DESC), B (ASC/DESC)" 의 의미는

A 기준으로 정렬하되, 동일한 A 발생시, B 기준으로 정렬한다는 의미

 

Q. A에 ASC를 생략해도 같은 결과가 나오는가? 

SELECT ANIMAL_ID,NAME,DATETIME
FROM ANIMAL_INS
ORDER BY NAME, DATETIME DESC

A. 같은 결과가 나온다.

A와 B 조건은 따로기때문에

"ORDER BY A, B DESC" 로 쓴다고 해서 A 내림차순, B 내림차순 절대! 아니다!!

 

7. 상위 n개 레코드 - MySQL(LIMIT 사용), ORACLE(rownum, 서브쿼리문 사용)

동물 보호소에 가장 먼저 들어온 동물의 이름을 조회하는 SQL 문을 작성해주세요.

 

* mysql

SELECT NAME
FROM ANIMAL_INS
ORDER BY DATETIME LIMIT 1

Mysql 에서는 ORDER BY에 "LIMIT n "를 사용해서 조회할 레코드 상위 n개를 설정해주면 된다

Limit를 사용하면 ~부터 ~까지도 조회할 수 있다

즉,

ORDER BY DATETIME LIMIT 5, 9  : DATAETIME으로 정렬한 후, 상위 5번째부터 9번째까지 조회! 

 

* oracle

SELECT NAME
FROM (SELECT *
      FROM ANIMAL_INS
      ORDER BY DATETIME)
WHERE rownum = 1;

oracle은 살짝 복잡하다 rownum을 써야한다는 거까지는 알았는데 

SELECT NAME FROM ANIMAL_INS ORDER BY DATETIME WHERE rownum = 1;

로 썼다가 계속 에러가 났었다;; 

 

Q. rownum을 사용할 때, subquery를 사용해야 하는 이유?

 

A. rownum은 각 행에 대한 일련번호를 의미하는데, 선택된 테이블의 레코드에 자동으로 순차적으로 번호가 부여된다. 

따라서, 테이블을 선택한 후에 특정 칼럼으로 정렬하여도, rownum은 정렬 전에 설정한대로 부여되어 있다.. 

즉, rownum은 테이블에 먼저 입력!(INSERT)된 순서대로 숫자가 부여되어서, 정렬을 하든 무슨짓을 하더라도 고유의 rownum을 가지고 있다..

따라서 원하는 테이블을 생성하여 사용해주면 되는데,, 그렇다고 새로운 테이블을 생성할 수도 없으니,, 

일시적으로 사용이 가능한 Inline view( from절에서 사용하는 subquery)를 사용한다!

생성된 테이블에 고유번호 rownum을 부여한 후에, 조건문을 사용하여 원하는 수 만큼 조회하면 된다!

 

 

프로그래머스 SQL 고득점 kit - SELECT

https://programmers.co.kr/learn/courses/30/parts/17042

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

알고리즘 효율성을 측정하는 가장 기본적인 방법은 시간과 메모리를 측정하는 것이다. 

파이썬에서는 해당 작업이 가능한데,,

 

수행시간 측정

import time

#측정 시작
start_time = time.time()

# 코드

#측정 종료
end_time = time.time()

#출력
print("time :", end_time-start_time)

 

예시

from random import randint
import time


array = []
for _ in range(10000):
    array.append(randint(1, 100))

start_time = time.time()
# 기본정렬 라이브러리
array.sort()
end_time = time.time()

print("기본 정렬 라이브러리 성능 측정 :", end_time - start_time)

array = []
for _ in range(10000):
    array.append(randint(1, 100))

start_time = time.time()
# 선택 정렬
for i in range(len(array)):
    min_index = i
    for j in range(i + 1, len(array)):
        if array[min_index] > array[j]:
            min_index = j
    array[i], array[min_index] = array[min_index], array[i]

end_time = time.time()

print("선택 정렬 성능 측정 :", end_time - start_time)

 

 

 

 

 

 

 

 

참고 : 이것이 코딩테스트다 - 동빈 나 

+ Recent posts