June 28, 2022
1.
5강
하나의 값 조작하기01.1 코드 값을 레이블로 변경하기
01.2 URL에서 요소 추출하기
01.3 문자열을 배열로 분해하기
01.4 날짜와 타임스탬프 다루기
01.5 결손 값을 디폴트 값으로 대치하기
2.
6강
여러 개의 값에 대한 조작02.1 문자열 연결하기
02.2 여러 개의 값 비교하기
02.3 2개의 값 비율 계산하기
02.4 두 값의 거리 계산하기
5강
하나의 값 조작하기데이터 가공해야하는 이유
여러 개의 정보가 하나의 문자열로 저장되어 있는 경우
어떤 값과 NULL을 연산하면 결과가 NULL이 되기 때문에
DROP TABLE IF EXISTS mst_users;
CREATE TABLE mst_users(
user_id varchar(255)
, register_date varchar(255)
, register_device integer
);
INSERT INTO mst_users
VALUES
('U001', '2016-08-26', 1)
, ('U002', '2016-08-26', 2)
, ('U003', '2016-08-27', 3)
;
select * from mst_users;
-- 5-1 코드를 레이블로 변경하는 쿼리
select
user_id,
case
when register_device = 1 then '데스크톱'
when register_device = 2 then '스마트폰'
when register_device = 3 then '애플리케이션'
end as device_name
from mst_users;
case 구문
사전 준비
DROP TABLE IF EXISTS access_log ;
CREATE TABLE access_log (
stamp varchar(255)
, referrer text
, url text
);
INSERT INTO access_log
VALUES
('2016-08-26 12:02:00', 'http://www.other.com/path1/index.php?k1=v1&k2=v2#Ref1', 'http://www.example.com/video/detail?id=001')
, ('2016-08-26 12:02:01', 'http://www.other.net/path1/index.php?k1=v1&k2=v2#Ref1', 'http://www.example.com/video#ref' )
, ('2016-08-26 12:02:01', 'https://www.other.com/' , 'http://www.example.com/book/detail?id=002' )
;
select * from access_log;
레퍼러로 어떤 웹 페이지를 커쳐 넘어왔는지 판별하기
-- 5-2 레퍼러 도메인을 추출하는 쿼리
select
stamp,
substring(referrer from 'https?://([^/]*)') as referrer_host
from access_log;
URL에서 경로와 요청 매개변수 값 추출하기
-- 5-3 URL 경로와 GET 매개변수에 있는 특정 키 값을 추출하는 쿼리
select
stamp,
url,
substring(url from '//[^/]+[^?#]+')as path,
substring(url from 'id=([^&]*)') as id
from access_log;
세부적으로 분해해서 사용하는 경우가 많음
사전 준비하기
DROP TABLE IF EXISTS access_log ;
CREATE TABLE access_log (
stamp varchar(255)
, referrer text
, url text
);
INSERT INTO access_log
VALUES
('2016-08-26 12:02:00', 'http://www.other.com/path1/index.php?k1=v1&k2=v2#Ref1', 'http://www.example.com/video/detail?id=001')
, ('2016-08-26 12:02:01', 'http://www.other.net/path1/index.php?k1=v1&k2=v2#Ref1', 'http://www.example.com/video#ref' )
, ('2016-08-26 12:02:01', 'https://www.other.com/' , 'http://www.example.com/book/detail?id=002' )
;
select * from access_log;
실습 쿼리
--- 5-4 URL경로를 슬래시로 분할해서 계층을 추출하는 쿼리
select
stamp,
url,
split_part(substring(url from '//[^/]+([^?#]+)'),'/',2) as path1,
split_part(substring(url from '//[^/]+([^?#]+)'),'/',3) as path2
from access_log;
PostgreSQL에서는 CURRENT_TIMESTAMP
의 리턴 값으로 타임존에 적용된 것이 나옴
LOCALTIMESTAMP
를 사용하는 것이 좋음실습 쿼리
--- 5-5 현재 날짜와 타임스탬프를 추출하는 쿼리
---- current_timestamp
select
current_date as dt,
current_timestamp as stamp
;
---- localhimestamp
select
current_date as dt,
localtimestamp as stamp
;
지정한 값의 날짜/ 시각 데이터 추출하기
--- 5-6 문자열 날짜 자료형, 타임스탬프 자료형으로 변환하는 쿼리
select
cast('2022-06-28' as date) as dt,
cast('2022-06-28 10:39:00' as timestamp) as stamp
;
날짜/ 시각에서 특정 필드 추출하기
--- 5-7 타임스탬프 자료형의 데이터에서 연, 월, 일 등을 추출하는 쿼리
select
stamp,
extract(year from stamp) as year,
extract(month from stamp) as month,
extract(day from stamp) as day,
extract(hour from stamp) as hour
from (select cast('2022-06-28 10:41:00' as timestamp) as stamp) as t
;
--- 5-8 타임스탬프를 나타내는 문자열에서 연, 월, 일 등을 추출하는 쿼리
---- substring
select
stamp,
substring(stamp, 1, 4) as year,
substring(stamp, 6, 2) as month,
substring(stamp, 9, 2) as day,
substring(stamp, 12, 2) as hour,
substring(stamp, 1, 7) as year_month
from (select cast('2022-06-28 10:45:00'as text)as stamp)as t;
---- substr
select
stamp,
substr(stamp, 1, 4) as year,
substr(stamp, 6, 2) as month,
substr(stamp, 9, 2) as day,
substr(stamp, 12, 2) as hour,
substr(stamp, 1, 7) as year_month
from (select cast('2022-06-28 10:45:00'as text)as stamp)as t;
문자열 또는 숫자를 다룰 때 중간에 NULL이 들어있는 경우 주의
사전 준비
DROP TABLE IF EXISTS purchase_log_with_coupon;
CREATE TABLE purchase_log_with_coupon (
purchase_id varchar(255)
, amount integer
, coupon integer
);
INSERT INTO purchase_log_with_coupon
VALUES
('10001', 3280, NULL)
, ('10002', 4650, 500)
, ('10003', 3870, NULL)
;
select * from purchase_log_with_coupon;
사용 쿼리
-- 5-9 구매액에서 할인 쿠폰 값을 제외한 매출 금액을 구하는 쿼리
select
purchase_id,
amount,
coupon,
amount - coupon as discount_amount1,
amount - coalesce(coupon, 0) as discount_amount2
from
purchase_log_with_coupon
;
6강
여러 개의 값에 대한 조작데이터 분석시 여러 값을 집약해서 하나의 값을 만들거나
새로운 지표 정의하기
사전 준비
DROP TABLE IF EXISTS mst_user_location;
CREATE TABLE mst_user_location (
user_id varchar(255)
, pref_name varchar(255)
, city_name varchar(255)
);
INSERT INTO mst_user_location
VALUES
('U001', '서울특별시', '강서구')
, ('U002', '경기도수원시', '장안구' )
, ('U003', '제주특별자치도', '서귀포시')
;
select * from mst_user_location;
사용 쿼리
--- 6-1 문자열을 연결하는 쿼리
---- concat() 사용
select
user_id,
concat(pref_name, city_name) as pref_city
from
mst_user_location
;
---- || 연산자 사용
select
user_id,
pref_name||city_name as pref_city
from
mst_user_location
;
사전 준비
DROP TABLE IF EXISTS quarterly_sales;
CREATE TABLE quarterly_sales (
year integer
, q1 integer
, q2 integer
, q3 integer
, q4 integer
);
INSERT INTO quarterly_sales
VALUES
(2015, 82000, 83000, 78000, 83000)
, (2016, 85000, 85000, 80000, 81000)
, (2017, 92000, 81000, NULL , NULL )
;
select * from quarterly_sales;
분기별 매출 증감 판정하기
-- 6-2 q1, q2 컬럼을 비교하는 쿼리
select
year,
q1,
q2,
case
when q1 < q2 then '+'
when q1 = q2 then ' '
else '-'
end as judge_q1_q2,
q2 - q1 as diff_q2_q1,
sign(q2 - q1) as sign_q2_q1
from
quarterly_sales
order by
year
;
연간 최대/ 최소 4분기 매출 찾기
--- 6-3 연간 최대/ 최소 4분기 매출을 찾는 쿼리
select
year,
greatest (q1, q2, q3, q4) as greatest_sales,
least (q1, q2, q3, q4) as least_sales
from
quarterly_sales
order by
year
;
연간 평균 4분기 매출 계산하기
--- 6-4 단순한 연산으로 평균 4분기 매출을 구하는 쿼리
select
year,
(q1 + q2 + q3 + q4) / 4 as average
from
quarterly_sales
order by
year
;
--- 6-5 COALESCE를 사용해 NULL을 0으로 변환하고 평균값을 구하는 쿼리
select
year,
(coalesce(q1,0) + coalesce(q2,0) + coalesce(q3,0) + coalesce(q4,0)) / 4 as average
from
quarterly_sales
order by
year
;
--- 6-6 NULL이 아닌 컬럼만을 사용해서 평균값을 구하는 쿼리
select
year,
(coalesce(q1,0) + coalesce(q2,0) + coalesce(q3,0) + coalesce(q4,0))
/ (sign(coalesce(q1,0))+ sign(coalesce(q2,0))
+sign(coalesce(q3,0)) + sign(coalesce(q4,0))) as average
from
quarterly_sales
order by
year
;
사전 준비
DROP TABLE IF EXISTS advertising_stats;
CREATE TABLE advertising_stats (
dt varchar(255)
, ad_id varchar(255)
, impressions integer
, clicks integer
);
INSERT INTO advertising_stats
VALUES
('2017-04-01', '001', 100000, 3000)
, ('2017-04-01', '002', 120000, 1200)
, ('2017-04-01', '003', 500000, 10000)
, ('2017-04-02', '001', 0, 0)
, ('2017-04-02', '002', 130000, 1400)
, ('2017-04-02', '003', 620000, 15000)
;
select * from advertising_stats;
정수 자료형의 데이터 나누기
--- 6-7 정수 자료형의 데이터를 나누는 쿼리
select
dt,
ad_id,
cast(clicks as double precision) / impressions as ctr,
100.0 * clicks / impressions as ctr_as_percent
from
advertising_stats
where
dt = '2017-04-01'
order by
dt, ad_id
;
0으로 나누는 것 피하기
컬럼명의 값이 0이라면 NULL
--- 6-8 0으로 나누는 것을 피해 CTR을 계산하는 쿼리
select
dt,
ad_id,
case
when impressions > 0 then 100.0 * clicks / impressions
end as ctr_as_percent_by_case,
100.0 * clicks / nullif(impressions, 0) as ctr_as_percent_by_null
from
advertising_stats
order by
dt, ad_id
;
작년 매출과 올해 매출에 어느 정도 차이가 있는지 등을 거리라고 부름
사전 준비
DROP TABLE IF EXISTS location_1d;
CREATE TABLE location_1d (
x1 integer
, x2 integer
);
INSERT INTO location_1d
VALUES
( 5 , 10)
, (10 , 5)
, (-2 , 4)
, ( 3 , 3)
, ( 0 , 1)
;
select * from location_1d;
DROP TABLE IF EXISTS location_2d;
CREATE TABLE location_2d (
x1 integer
, y1 integer
, x2 integer
, y2 integer
);
INSERT INTO location_2d
VALUES
(0, 0, 2, 2)
, (3, 5, 1, 2)
, (5, 3, 2, 1)
;
select * from location_2d;
숫자 데이터의 절댓값, 제곱 평균 제곱근(RMS) 계산하기
제곱근 구할 때 SQRT함수를 사용
--- 6-9 일차원 데이터의 절댓값과 제곱 평균 제곱근을 계산하는 쿼리
select
abs(x1 - x2) as abs,
sqrt(power(x1 - x2, 2)) as rms
from location_1d
;
xy 평면 위에 있는 두 점의 유클리드 거리 계산하기
postgreSQL에는 POINT 자료형이라고 불리는 좌표를 다루는 자료구조 가 있음
--- sqrt(power())
select
sqrt(power(x1 - x2, 2) + power(y1 - y2, 2)) as dist
from location_2d
;
--- point <-> 사용
select
point(x1,y1) <-> point(x2,y2) as dist
from location_2d
;