2020. 6. 7. 21:21ใETC/Algorithm
๐ ๋ฌธ์
ANIMAL_OUTS ํ ์ด๋ธ์ ๋๋ฌผ ๋ณดํธ์์์ ์ ์ ๋ณด๋ธ ๋๋ฌผ์ ์ ๋ณด๋ฅผ ๋ด์ ํ ์ด๋ธ์ ๋๋ค. ANIMAL_OUTS ํ ์ด๋ธ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ผ๋ฉฐ, ANIMAL_ID, ANIMAL_TYPE, DATETIME, NAME, SEX_UPON_OUTCOME๋ ๊ฐ๊ฐ ๋๋ฌผ์ ์์ด๋, ์๋ฌผ ์ข , ์ ์์ผ, ์ด๋ฆ, ์ฑ๋ณ ๋ฐ ์ค์ฑํ ์ฌ๋ถ๋ฅผ ๋ํ๋ ๋๋ค. ๋ณดํธ์์์๋ ๋ช ์์ ์ ์์ด ๊ฐ์ฅ ํ๋ฐํ๊ฒ ์ผ์ด๋๋์ง ์์๋ณด๋ ค ํฉ๋๋ค. 0์๋ถํฐ 23์๊น์ง, ๊ฐ ์๊ฐ๋๋ณ๋ก ์ ์์ด ๋ช ๊ฑด์ด๋ ๋ฐ์ํ๋์ง ์กฐํํ๋ SQL๋ฌธ์ ์์ฑํด์ฃผ์ธ์. ์ด๋ ๊ฒฐ๊ณผ๋ ์๊ฐ๋ ์์ผ๋ก ์ ๋ ฌํด์ผ ํฉ๋๋ค.
NAME | TYPE | NULLABLE |
ANIMAL_ID | VARCHAR(N) | FALSE |
ANIMAL_TYPE | VARCHAR(N) | FALSE |
DATETIME | DATETIME | FALSE |
NAME | VARCHAR(N) | TRUE |
SEX_UPON_OUTCOME | VARCHAR(N) | FALSE |
์์
SQL๋ฌธ์ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋์์ผ ํฉ๋๋ค.
HOUR | COUNT |
0 | 0 |
1 | 0 |
2 | 0 |
3 | 0 |
4 | 0 |
5 | 0 |
6 | 0 |
7 | 3 |
8 | 1 |
9 | 1 |
10 | 2 |
11 | 13 |
12 | 10 |
13 | 14 |
14 | 9 |
15 | 7 |
16 | 10 |
17 | 12 |
18 | 16 |
19 | 2 |
20 | 0 |
21 | 0 |
22 | 0 |
23 | 0 |
๐ ฐ ํ์ด
๋ชป ํ์ด์ ๋จธ๋ฆฌ๋ฅผ ๋๋ ์ธ๋งค๋ ๋์๊ฒ ํ ์ค๊ธฐ ๋น๊ณผ ๊ฐ๋ ๋ฐ์ ๋งํฌโจ(๊ฐ์ฌํฉ๋๋ค๐)
ํด๋น ํฌ์คํ ์ ์ ๋งํฌ์ ๋์จ sql๋ฌธ์ ํ์ดํ๋ ๊ณผ์ ์ ๋ํ ํฌ์คํ ์ ๋๋ค.
SELECT l.hour, nvl(count, 0) AS count
FROM (SELECT TO_CHAR(datetime, 'HH24') AS hour, count(*) AS count
FROM animal_outs
GROUP BY TO_CHAR(datetime, 'HH24')
ORDER BY hour) O,
(SELECT LEVEL-1 AS hour FROM dual CONNECT BY LEVEL<=24) L
WHERE L.hour = O.hour(+)
ORDER BY L.hour;
์ sql์ ์คํํ๋ฉด ๋ฌธ์ ์ ์์์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
์ด์ ๋ถํฐ ํ๋ํ๋ ๋ฏ์ด๋ณด๊ฒ ์ต๋๋ค.
โก๏ธ TO_CHAR
SELECT TO_CHAR(datetime, 'HH24') AS hour, count(*) AS count
FROM animal_outs
GROUP BY TO_CHAR(datetime, 'HH24')
ORDER BY hour
์ด๋ ํ๋ก๊ทธ๋๋จธ์ค SQL LEVEL 2์ ์ ์ ์๊ฐ ๊ตฌํ๊ธฐ ๋ฌธ์ ๋ฅผ Oracle๋ก ์์ฑํ ํ์ด์ ๋น์ทํฉ๋๋ค.
์ค๋ผํด์์ ๋ ์ง ํฌ๋งท์ ๋ณํ์ TO_CHARํจ์๋ฅผ ์ด์ฉํฉ๋๋ค.
์ datetime ์ปฌ๋ผ์ ํ์ ์ datetime์ ๋๋ค. datetime type์ DATE, TIMESTAMP, TIMESTAMP WITH LOCAL TIME ZONE ํ์ ์ ๋๋ค.
Oracle์์ SYSDATE๋ฅผ ๊ฐ์ ธ์ค๋ ์ฟผ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
SELECT SYSDATE FROM DUAL;
์ ์ฟผ๋ฆฌ๋ฅผ ์คํ์ํค๋ฉด 2020-06-07 11:04:25๋ก ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
ํจ์์ ๊ธฐ๋ณธํ์ TO_CHAR(์ซ์/๋ ์ง , FORMAT)์ ๋๋ค. ๋ ์งํจ์ SYSDATE๋ฅผ ์ด์ฉํ์ฌ TO_CHAR์ ๋ํด ์์๋ด ์๋ค.
SELECT
--๋ ์ง ํฌ๋งท
TO_CHAR(SYSDATE,'YYYYMMDD'),--20200607
TO_CHAR(SYSDATE,'YYYY-MM-DD'),--2020-06-07
TO_CHAR(SYSDATE,'YYYY/MM/DD'),--2020/06/07
TO_CHAR(SYSDATE,'YYYY'),--2020
TO_CHAR(SYSDATE,'YY'),--20
TO_CHAR(SYSDATE,'MM'),--06
TO_CHAR(SYSDATE,'MON'),--JUN
TO_CHAR(SYSDATE,'D'),--1 (์ฃผ์ค์ ์ผ์ 1~7๋ก ํ์(์ผ์์ผ = 1)
TO_CHAR(SYSDATE,'DD'),--07
TO_CHAR(SYSDATE,'DDD'),--159 (1๋
๊ธฐ์ค ์ผ ์)
TO_CHAR(SYSDATE,'DAY'),--SUNDAY (์์ผ ํ์)
TO_CHAR(SYSDATE,'DY'), --SUN (์์ผ์ ํ์๋ฆฌ๋ก ํ์)
TO_CHAR(SYSDATE,'WW'), -- 23 (์ผ๋
๊ธฐ์ค ์ฃผ๋ฅผ 00 ~ 53 ํํ๋ก ํ์)
TO_CHAR(SYSDATE,'W'), -- 1 (ํ๋ฌ ๊ธฐ์ค ๋ช๋ฒ์งธ ์ฃผ)
TO_CHAR(SYSDATE,'DL'),--Sunday, June 07, 2020
--์ฌ๊ฐ ํฌ๋งท
TO_CHAR(SYSDATE,'AM'),--AM
TO_CHAR(SYSDATE,'PM'),--AM
TO_CHAR(SYSDATE,'HH'), --11 (์๊ฐ์ 0 ~ 12 ํํ๋ก ํ์)
TO_CHAR(SYSDATE,'HH24'), --11 (์๊ฐ์ 0 ~ 24 ํํ๋ก ํ์)
TO_CHAR(SYSDATE,'MI'), --15 (๋ถ์ 00 ~ 59 ํํ๋ก ํ์)
TO_CHAR(SYSDATE,'SS'), --51 (์ด์ 01 ~ 59 ํํ๋ก ํ์)
--์ธ๊ธฐ ํฌ๋งท
TO_CHAR(SYSDATE,'CC'), --21 (์ธ๊ธฐ)
TO_CHAR(SYSDATE,'BC') --AD
FROM DUAL;
โก๏ธ CONNECT BY
SELECT LEVEL-1 AS hour FROM dual CONNECT BY LEVEL<=24;
Oracle์์๋ ๊ณ์ธต ๋ฐ์ดํฐ๋ฅผ ์ํด CONNECT BY ์ ์ ์ง์ํฉ๋๋ค.
(์ค๋ผํด์์ ๊ณ์ธตํ ์ฟผ๋ฆฌ๋ START WITH... CONNECT BY ์ ๋ก ์์ฑํ ์ ์์ต๋๋ค. ํด๋น ํฌ์คํ ์์ START WITH์ ์ธ๊ธํ์ง ์์ต๋๋ค.)
CONNECT BY ์ ์ ๊ฒฐ๊ณผ์๋ LEVEL์ด๋ผ๋ ์นผ๋ผ์ด ์์ผ๋ฉฐ, ์ด๋ ๊ณ์ธต์ ๊น์ด๋ฅผ ์๋ฏธํฉ๋๋คโ๏ธ
LEVEL ํจ์๋ฅผ ์ด์ฉํ๋ฉด ์์ฐจ์ ๋ชฉ๋ก์ ์์ํ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
SELECT LEVEL FROM dual CONNECT BY LEVEL <=5;
์ด SQL๋ฌธ์ ์คํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
LEVEL |
1 |
2 |
3 |
4 |
5 |
๋ฐ๋ผ์ ๋ฌธ์ ์ ์๋์ ๋ง๊ฒ 0๋ถํฐ 24๊น์ง์ ์ซ์๋ฅผ ์์๋๋ก ์ถ๋ ฅํ๋ ค๋ฉด SELECT ๋ฌธ์ LEVEL-1์ ์์ฑํ๊ณ , CONNECT BY์ ์๋ LEVEL<=24๋ผ๋ ์กฐ๊ฑด์ ๊ฑธ์ด์ฃผ์ด์ผ ํฉ๋๋ค.
CONNECT BY LEVEL์ ์ด์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ SQL๋ฌธ์ ์์ฑํ ์๋ ์์ต๋๋ค. ์ค๋ ๋ ์ง๋ก๋ถํฐ 10์ผ๊ฐ์ ๋ ์ง๋ฅผ ์์๋๋ก ์ถ๋ ฅํ๋ SQL๋ฌธ์ ๋๋ค. LEVEL์ 1๋ถํฐ ์์ํ๊ธฐ ๋๋ฌธ์ LEVEL-1์ ํตํด ์ค๋ ๋ ์ง๋ถํฐ ์ถ๋ ฅํ๋๋ก ํ์ต๋๋ค.
SELECT TO_CHAR(TO_DATE(sysdate,'YY-MM-DD')+LEVEL-1, 'YY-MM-DD')
FROM dual CONNECT by level <= 10;
์ด๋ฅผ ์คํํ๋ฉด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
to_char(to_date(sysdate,'yy-mm-dd')+level-1,'yy-mm-dd') |
07-06-20 |
07-06-21 |
07-06-22 |
07-06-23 |
07-06-24 |
07-06-25 |
07-06-26 |
07-06-27 |
07-06-28 |
07-06-29 |
โก๏ธ OUTER JOIN
WHERE L.hour = O.hour(+)
์กฐ์ธํ๋ ์ฌ๋ฌ ํ ์ด๋ธ์์ ํ ์ชฝ์๋ ๋ฐ์ดํฐ๊ฐ ์๊ณ , ํ์ชฝ์๋ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ, ๋ฐ์ดํฐ๊ฐ ์๋ ์ชฝ ํ ์ด๋ธ์ ๋ด์ฉ์ ๋ชจ๋ ์ถ๋ ฅํ๋ ๊ฒ์ ๋๋ค. ์ฆ, ์กฐ๊ฑด์ ๋ง์ง ์์๋ ํด๋นํ๋ ํ์ ์ถ๋ ฅํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ ์์ ์ผ๋ก ์กฐ์ธ ์กฐ๊ฑด์ ๋ง์กฑํ์ง ๋ชปํ๋ ํ๋ค๋ ์ถ๋ ฅํ๊ธฐ ์ํด OUTER JOIN์ ์ฌ์ฉํฉ๋๋ค.
โ๏ธOracle์์ OUTER JOIN ์ฐ์ฐ์๋ (+) ์ ๋๋ค.
โ๏ธ์กฐ์ธ์ํฌ ๊ฐ์ด ์๋ ์กฐ์ธ ์ธก์ (+)๋ฅผ ์์น์ํต๋๋ค.
โ๏ธOUTER JOIN ์ฐ์ฐ์๋ ํํ์์ ํ ํธ์๋ง ์ฌ ์ ์์ต๋๋ค.
โ๏ธ๋งค์นญ๋๋ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ, NULL๋ก ํ์ํฉ๋๋ค.
SQL๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ด ๋ฐ๊พผ๋ค๋ฉด, ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ต๋๋ค.
WHERE L.hour(+) = O.hour
HOUR | COUNT |
7 | 3 |
8 | 1 |
9 | 1 |
10 | 2 |
11 | 13 |
12 | 10 |
13 | 14 |
14 | 9 |
15 | 7 |
16 | 10 |
17 | 12 |
18 | 16 |
19 | 2 |
O.hour์ด L.hour์ ๊ฐ์ ๋ชจ๋ ํฌํจํ๊ณ ์๊ธฐ ๋๋ฌธ์ L.hour์ ๊ฐ๋ง ๋์ค๊ฒ ๋ฉ๋๋ค.
โก๏ธ NVL
SELECT l.hour, nvl(count, 0) AS count
NVL์ ์ค๋ผํด์๋ง ์๋ ํจ์๋ก, NVL ํจ์๋ ๊ฐ์ด null์ธ ๊ฒฝ์ฐ ์ง์ ๊ฐ์ ์ถ๋ ฅํฉ๋๋ค.
์ SQL๋ฌธ์์๋ count๊ฐ null์ธ ๊ฒฝ์ฐ 0์ ์ถ๋ ฅํ๋๋ก ํฉ๋๋ค.
๐ค BONUS !
Oracle์๋ NVL2๋ ์์ต๋๋ค!
NVL2("์ปฌ๋ผ๋ช
", "์ง์ ๊ฐ1", "์ง์ ๊ฐ2");
NVL2๋ null์ด ์๋ ๊ฒฝ์ฐ ์ง์ ๊ฐ1์ ์ถ๋ ฅํ๊ณ , null์ธ ๊ฒฝ์ฐ ์ง์ ๊ฐ2๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
๐ ์ฐธ๊ณ ๋งํฌ