상근이는 매일 아침 알람을 듣고 일어난다. 알람을 듣고 바로 일어나면 다행이겠지만, 항상 조금만 더 자려는 마음 때문에 매일 학교를 지각하고 있다. 상근이는 모든 방법을 동원해보았지만, 조금만 더 자려는 마음은 그 어떤 것도 없앨 수가 없었다. 이런 상근이를 불쌍하게 보던, 창영이는 자신이 사용하는 방법을 추천해 주었다. 바로 "45분 일찍 알람 설정하기"이다. 이 방법은 단순하다. 원래 설정되어 있는 알람을 45분 앞서는 시간으로 바꾸는 것이다. 어차피 알람 소리를 들으면, 알람을 끄고 조금 더 잘 것이기 때문이다. 이 방법을 사용하면, 매일 아침 더 잤다는 기분을 느낄 수 있고, 학교도 지각하지 않게 된다. 현재 상근이가 설정한 알람 시각이 주어졌을 때, 창영이의 방법을 사용한다면, 이를 언제로 고쳐야 하는지 구하는 프로그램을 작성하시오.
#include <stdio.h>
int main() {
int hour, min;
int phour = 0;
int pmin = 0;
scanf("%d %d", &hour, &min);
if (min >= 45) {
pmin = min - 45;
phour = hour;
}
else {
pmin = 60 - (45 - min);
if (hour == 0)
phour = 23;
else
phour = hour - 1;
}
printf("%d %d", phour, pmin);
}
n = (1.96 / 1.5)² x 25 = 42.68 => 최소 43개의 표본이 필요하다.
2. 분산 (표준편차)
모집단 가정 : N(μ, σ²) // 정규성에 대한 가정확인 필요
확률 표본 : X1, X2, ..., Xn ~ iid N(μ, σ²)
2.1 점추정
모수 σ <= 표본분산 : S² = 1 / (n-1) ∑ (xi - x̅)²
모수 σ² <= 표본표준편차 : S = √1 )/ (n-1) ∑ (xi - x̅)²
중심축량 = (n - 1) S² / σ² ~χ²(n-1) // 유도는 '수리통계학'에서
예를 들어, 16개의 표본으로 σ²의 95% 신뢰구간을 구해보자.
정규분포와 t-분포는 0을 중심으로 대칭이기 때문에 0.5를 반으로 나눈 면적을 이용해서 가장 짧은 구간. 구할 수 있었다. 하지만, 카이제곱분포는 비대칭 형태이기 때문에 절반으로 나눈 것보다 더 짧은 구간을 구할 방법이 있다. 그러나 그 값은 구하기 매우 어렵기 때문에 카이제곱분포에서도 절반으로 나눠서 구간을 구한다.
3) 사용자가 발생한 SQL과 그 실행계획시 라이브러리캐시(프로시저캐시)에 캐싱되어 있는지 확인
4) 캐싱되어 있다면 소프트파싱, 캐싱되어있지 않다면 하드파싱
으로 구성된다.
* 소프트파싱: SQL과 실행계획을 캐시에서 찾아 곧바로 실행단계로 넘어가는 경우
* 하드파싱: SQL과 실행계획을 캐시에서 찾지 못해 최적화 과정을 거치고나서 실행단계로 넘어가는 경우
* 라이브러리캐시는 해시구조로 엔진에서 관리된다. SQL마다 해시값에 따라 여러 해시 버킷으로 나뉘며 저장되고, SQL을 찾을 때는 SQL 문장을 해시 함수에 적용하여 반환되는 해시값을 이용해서 해시 버킷을 탐색한다.
2. 규칙기반 옵티마이저 (RBO)
실행계획을 정해진 룰에 따라 만든다.
룰은 데이터베이스 엔진마다 여러 가지가 있다.
예를 들어서 오라클의 RBO는 다음과 같다.
순위
액세스 경로
1
Single Row by Rowid
2
Single Row by Cluster Join
3
Single Row by Hash Cluster Key with Unique or Primary Key
4
Single Row by Unique or Primary Key
5
Clustered Join
6
Hash Cluster Key
7
Indexed Cluster Key
8
Composite Index
9
Single-Column Indexes
10
Bounded Range Search on Indexed Columns
11
Unbounded Range Search on Indexed Columns
12
Sort Merge Join
13
MAX or MIN of Indexed Column
14
ORDER BY on Indexed Column
15
Full Table Scan
자세한 과정은 잘 모르겠지만, 크게 보면 엑세스를 할 때에 인덱스를 이용하느냐, 전체 테이블을 스캔하느냐 등으로 나눌 수 있다. 1번부터 순서대로 맞는 경우에 진행하며, 아래로 갈수록 data가 흐트러져서 저장되기 때문에 비용이 많이 든다.
그리고 요즘에는 대부분 RBO보다 CBO를 이용한다.
3. 비용기반 옵티마이저 (CBO)
비용을 기반으로 최적화를 수행하는 방식이다. 이때 비용이란 쿼리를 수행하는데 소요되는 일의 양 또는 시간 예상치이다.
딕셔너리에서 테이블과 인덱스를 통해 레코드 개수, 블록 개수, 평균 행 길이, 칼럼 값의 수, 칼럼 값 분포, 인덱스 높이, 클러스터링 팩터 등의 통계값을 기반으로 비용을 예측하는 방식이다. 이 예측된 비용에 따라 최적의 실행 계획을 도출한다. 최근에는 추가적으로 하드웨어적 특성을 반영한 시스템 통계정보 (CPU 속도, 디스크 I/O 속도 등)까지 이용한다.
4. SQL 실행계획
실행 계획은 SQL에서 요구한 사항을 처리하기 위한 절차와 방법을 의미한다. 즉, SQL을 어떤 순서로 어떻게 진행할 지 결정한다는 것이다.
실행 계획의 구성요소는 다음 다섯 가지가 있다.
조인 순서 (Join Order) : JOIN 수행에서 어떤 테이블이 먼저 조회되는가
조인 기법 (Join Method) : loop, merge, sorting 등
액세스 기법 (Access Method) : Index / Full table 등
최적화 정보 (Optimization Information) : 알고리즘
연산 (Operation) : 크다, 작다, 함수, MAX, MIN 등
5. INDEX
INDEX는 데이터베이스 분야에 있어서 테이블에 대한 동작의 속도를 높여주는 자료 구조이다.
CREATE INDEX IDX_### ON db, table (column);
ALTER TABLE db.table ADD INDEX IDX_###;
두 코드 모두 column에 대한 INDEX를 생성하는 코드이다.
ALTER TABLEdb.tableDROP INDEXIDX_###;
테이블에 있는 인덱스를 삭제하는 코드이다.
EXPLAIN SELECT * FROM db.table;
실행 계획을 확인하는 코드이다.
예제)
DESC kaggle.titanic;
EXPLAIN SELECT * FROM kaggle.titanic WHERE `Age` = 23;
>> Age가 23인 데이터를 찾기 위해 418개의 rows를 모두 검색하는 것이 플랜임을 알 수 있다.
[INDEX 생성 후]
DESCkaggle.titanic;
Age에 인덱스가 생성된 것을 확인할 수 있다.
EXPLAIN SELECT*FROMkaggle.titanicWHERE`Age` = 23;
>> IDX_AGE를 사용해서 reference를 통해서 쿼리를 실행하는 것이 플랜임을 알 수 있다.
가장 위에 파란 글씨로 써져있는 것은 데이터 타입 느낌의 분류체계이다. Abc는 문자열, #은 상수, 지구 모양은 지리에 관한 것이다. 그리고, 이 파일의 경우는 분류가 F1, F2 등으로 되어있는데, 이 부분을 더블클릭해서 원하는 인덱스명으로바꿀 수 있다. 뒤에서 시각화 할 때 구분하기 쉽도록 미리 바꿔놓는 것이 좋다.
이러한 식으로 분류할 수 있다.
본격적으로 시각화를 하기 위해 시트1 옆에 있는 작은 버튼 (새 워크시트) 을 눌러준다.
그러면 이러한 창이 뜬다.
1) 막대 그래프
"필터" 부분에 '시도명' 테이블을 가져와서 서울과 부산 중 서울만 선택했다.
표는 대분류를 열로, 측정값을 행으로 하여 대분류에 따른 데이터 수를 막대 그래프로 시각화했다.
간단하게 옆의 테이블에서 끌어와서 원하는 부분에 놓으면 된다.
필터에 '시군구' 테이블을 가져와서 용산구의 값만 나타냈다.
그래프 왼쪽에 Y축 부분에 마우스를 가져가면 오름차순, 내림차순 정렬도 할 수 있다.
2) 지도
다음은 지도에 시각화하기 위해 데이터 파일에 포함되어 있었던 '경도'와 '위도'를 각각 열과 행에 넣어줬다.
그러면 이렇게 지도가 나온다. 맵 - 맵 계층에 들어가서 스타일도 변경할 수 있다.
서울에 있는 데이터들만 표현한 것이다.
"마크"에서 모양, 크기, 색상 등을 변경할 수 있다.
확대해보면 한강 위에 정보가 찍혀있는 오류도 발견할 수 있다.
"마크"에서 모양을 변경하여 밀도도 확인할 수 있다.
"필터"에 '시군구'와 '대분류'를 포함하여 용산구에 있는 학문/교육 시설만 나타낸 것이다.
예를 들어 95% 신뢰구간을 구할 때, P(158.78 ≤ μ ≤ 166.62) 이라면 신뢰구간은 [158.78, 166.62]이다.
하지만, 이때 μ가 신뢰구간에 포함될 확률은 0.95가 아니라 0 또는 1이다.
신뢰구간이 [x̅ - Z(α/2) ·σ /√n,x̅ + Z(α/2) · σ / √n ] 와 같이 확률변수로 표현될 때는 신뢰구간에 포함될 확률이 0.95이겠지만, 실제 자료로 구간을 구하면 그 구간은 "상수"로 표현되기 때문에 상수 μ가 상수 범위에 포함될 확률은 0또는1이 되는 것이다.
그렇다면 실제 데이터를 통해 상수로 표현될 때, 0.95는 무엇을 의미할까.
위의 경우, 한 번 데이터를 뽑아 만든 신뢰구간이 [158.78, 166.62]이다.
그리고 또 다시 데이터를 뽑아서 신뢰구간을 만들 수 있다. 이렇게 데이터를 새로 뽑으면 표본평균(x̅)이 바뀐다.
그래서 새로 데이터를 10000번 뽑아서 신뢰구간을 10000개 구했을 때, 그 중 9500번 정도에 모평균μ가 포함된다는 의미이다.
4. 가설 검정
가설을 설정하고, 그에 대한 옳고 그름을 표본으로부터 얻은 정보를 통해 확률적으로 판단하는 방법이다.
가설에는 귀무가설과 대립가설이 있다.
대립가설 (H1) 은 표본으로부터 얻은 증거에 의해 우리가 입증하고자 하는 가설이다.
귀무가설 (H0) 은 대립가설의 반대되는 가설로, 검정의 대상이 되는 가설이다.
수학의 '귀류법'과 유사하게, 직접 대립가설을 입증하기 어려운 경우가 많기 때문에, 그에 반대되는 가설인 귀무가설이 잘못됨을 입증하여 대립가설을 입증하는 방법을 이용한다.
즉, [정상적인 표본 => 대립가설 참] 을 입증하는 방법이 어렵기 때문에,
[귀무가설 참 => 비정상적인 표본]을 입증하는 방법을 이용하는 것이다.
정상 / 비정상적인 표본을 구분하는 방법은 표본이 발생할 수 있는 가능성을 통해 구분한다. 비정상적인 표본은 자주 발생하지 않는 표본이다.
이 가능성은 "유의 수준"을 이용해 판단하고 이때 "검정 통계량"을 이용한다.
1) 검정 통계량
귀무가설을 기각시킬 것인가, 채택할 것인가 결정하기 위해 사용되는 통계량이다.
검정 통계량 유도 방법은 '수리통계학'에서 다룬다.
귀무가설 하에서 검정 통계량의 확률 분포를 이용하여 표본의 정상 / 비정상을 판정한다.
비정상 표본은 "기각역"에, 정상적인 표본은 "채택역"에 위치한다.
앞에서 말했듯이 정상, 비정상의 기준은 유의수준으로 결정한다.
예를 들어서, 초코파이를 새로 만든다고 해보자. 기존 파이의 평균 칼로리는 45kcal였고, 가설 검정을 통해 새로운 파이는 기존의 파이보다 칼로리가 낮다는 것을 보이고자 한다.
이때 대립가설은 H1: μ < 45 이고, 귀무가설은 H0: μ ≥ 45 이다.
그렇다면, 귀무가설과 반대되도록 표본평균 x̅이 45보다 작을수록 비정상 자료라고 할 수 있다.
표본평균이 45보다 작을 경우 귀무가설이 옳지 않음을 보여주는 비정상 자료이기 때문에 귀무가설을 기각시킬 수 있다.
2) 오류의 종류
결정 // 실제
귀무가설 사실
대립가설 사실
귀무가설 사실
O
제 2종 오류
대립가설 사실
제 1종 오류
O
º α = maxP( 제 1종 오류 ) = P( H0 기각 | H0 사실 ) : 제 1종 오류를 범할 확률
α : 유의 수준
귀무가설의 경계값에서 P( 제 1종 오류)가 최대가 된다.
º β = 1 - P( 제 2종 오류 ) = 1 - P( H0 채택 | H1 사실 ) : 제 2종 오류를 범할 확률
조건 1) 자바 클래스 파일명을 Exam2.java 로 한다. 조건 2) main()을 만든다. 조건 3) for 루프를 이용하여 1에서부터 100까지 3의 배수의 전체 합을 구하는 프로그램을 작성한다.
package exam2;
public class Exam2 {
public static void main(String[] args) {
int total = 0;
for (int i = 0; i <= 100; i++) {
if (i % 3 == 0)
total += i;
else continue;
System.out.println("sum = " + total + ", i = " + i);
}
System.out.println("total = " + total);
}
}
create database kaggle;
use kaggle;
CREATE TABLE `org_test_import` (
`PassengerId` int NULL,
`Pclass` int NULL,
`Name` text,
`Sex` text,
`Age` text,
`SibSp` int NULL,
`Parch` int NULL,
`Ticket` text,
`Fare` text,
`Cabin` text,
`Embarked` text
) ENGINE=InnoDB ;
SELECT @@sql_mode;
set @@sql_mode = "";
CREATE TABLE `test` (
`PassengerId` int NULL,
`Pclass` int NULL,
`Name` text,
`Sex` text,
`Age` double,
`SibSp` int NULL,
`Parch` int NULL,
`Ticket` text,
`Fare` double,
`Cabin` text,
`Embarked` text
) ENGINE=InnoDB ;
INSERT INTO `kaggle`.`test` (
`PassengerId`,
`Pclass`,
`Name`,
`Sex`,
`Age`,
`SibSp`,
`Parch`,
`Ticket`,
`Fare`,
`Cabin`,
`Embarked` )
SELECT `org_test_import`.`PassengerId`,
`org_test_import`.`Pclass`,
`org_test_import`.`Name`,
`org_test_import`.`Sex`,
`org_test_import`.`Age`,
`org_test_import`.`SibSp`,
`org_test_import`.`Parch`,
`org_test_import`.`Ticket`,
`org_test_import`.`Fare`,
`org_test_import`.`Cabin`,
`org_test_import`.`Embarked`
FROM `kaggle`.`org_test_import`;
select age from `org_test_import`;
select age from `kaggle`.`test`;
SELECT * FROM `gender_submission`;
ALTER TABLE `test` ADD PRIMARY KEY (`PassengerId`);
ALTER TABLE `gender_submission` ADD PRIMARY KEY (`PassengerId`);
ALTER TABLE `gender_submission` ADD FOREIGN KEY (`PassengerId`) REFERENCES `test` (`PassengerId`);
SELECT COUNT (*) FROM `gender_submission`;
SELECT COUNT (*) FROM `test`;
SELECT COUNT (*) FROM test A JOIN gender_submission B ON A.PassengerId = B.PassengerId;
CREATE TABLE `titanic` (
`PassengerId` int not NULL,
`Pclass` int NULL,
`Name` text,
`Sex` text,
`Age` double,
`SibSp` int NULL,
`Parch` int NULL,
`Ticket` text,
`Fare` double,
`Cabin` text,
`Embarked` text,
`Survived` int ,
primary key (`PassengerId` )
) ENGINE=InnoDB ;
INSERT INTO `kaggle`.`titanic` (
`PassengerId`,
`Pclass`,
`Name`,
`Sex`,
`Age`,
`SibSp`,
`Parch`,
`Ticket`,
`Fare`,
`Cabin`,
`Embarked`,
`Survived`)
SELECT
A.`PassengerId`,
`Pclass`,
`Name`,
`Sex`,
`Age`,
`SibSp`,
`Parch`,
`Ticket`,
`Fare`,
`Cabin`,
`Embarked`,
B.`Survived`
FROM test A JOIN gender_submission B ON A.PassengerId = B.PassengerId ;
SELECT COUNT(*) FROM `kaggle`.`titanic` ;
SELECT * FROM `kaggle`.`titanic` ;
SELECT MAX(`Age`) FROM `kaggle`.`titanic`;
SELECT MIN(`Age`) FROM `kaggle`.`titanic` WHERE `Age` > 0;
SELECT AVG(`Age`), COUNT(*) FROM `kaggle`.`titanic` WHERE `Age` > 0;
SELECT sum(`Fare`) FROM `kaggle`.`titanic`;
SELECT `Name`, `Pclass`, `Sex`, `Age` FROM `kaggle`.`titanic` ORDER BY 1 ; ##첫번째 컬럼 기준으로 오름차순 (Name)
SELECT `Name`, `Pclass`, `Sex`, `Age` FROM `kaggle`.`titanic` ORDER BY 3 ;
SELECT `Name`, `Pclass`, `Sex`, `Age` FROM `kaggle`.`titanic` ORDER BY `Name` DESC ;
#10개 제한된 행 조회
SELECT * FROM `kaggle`.`titaic` WHERE `Name` LIKE 'A%' LIMIT 10; #이름이 A로 시작하는 row 10개
##`PassengerId` 유일한 값만 조회
SELECT DISTINCT `PassengerId` FROM `kaggle`.`titanic`;
SELECT DISTINCT `Sex` FROM `kaggle`.`titanic`;
SELECT `Sex`, COUNT(*) FROM `kaggle`.`titanic` GROUP BY 1; #첫번째 컬럼을 그룹화해서 카운트
SELECT `Sex`, COUNT(*) CNT FROM `kaggle`.`titanic` GROUP BY `Sex` HAVING CNT > 200; #count = cnt, cnt가 200이상인 그룹의 카운트 수
SELECT `Sex`, `survived`, COUNT(*) FROM `kaggle`.`titanic` GROUP BY `Sex`, `Survived` ;
##floor = 반올림
#연령 밴드별 조회
SELECT floor(`Age`/10) * 10 + 10, COUNT(*) FROM `kaggle`.`titanic` WHERE `Age` > 0 group by 1; #~대 미만 승객 수
SELECT floor(`Age`/10) * 10 + 10, COUNT(*) FROM `kaggle`.`titanic` WHERE `Age` > 0 group by 1 order by 1;
SELECT floor(`Age`/10) * 10 + 10, COUNT(*) FROM `kaggle`.`titanic` WHERE `Age` > 0 group by 1 order by 1 desc;
SELECT floor(`Age`/10) * 10 + 10, `survived`, COUNT(*) CNT FROM `kaggle`.`titanic`
WHERE `Age` > 0 group by 1, 1 HAVING CNT > 40 order by 1 desc, 2 desc;
#서브쿼리
SELECT * FROM `kaggle`.`titanic`
WHERE `PassengerId` IN (SELECT `PassengerId` FROM `test` WHERE `Age` = 0); # NULL 값이었던 passengerId(age=0)를 titanic table에서 조회해라
UPDATE `kaggle`.`titanic`
SET `Age` = 30.272590361445783
WHERE `PassengerId` IN (SELECT `PassengerId` FROM `test` WHERE `Age` = 0) ;
SELECT COUNT(*) FROM `gender_submission` ;
SELECT COUNT(*) FROM `test` ;
count( ) 는 투플의 개수를 세는 함수이다. FROM - 뒤에 WHERE - 을 붙여 조건을 걸 수 있다.
정확한 표현인지는 모르겠지만..
예제에 나온 SELECT COUNT(*) FROM 'gender_submission'; 은 'gender_submission' 테이블에 있는 전체 투플 수 (rows)를 count해준다.
SELECT COUNT(*) FROM test A JOIN gender_submission B ON A.PassengerId = B.PassengerId ;
'test' 테이블의 'PassengerId'와 'gender_submission'테이블의 'PassengerId'가 같을 경우에, 'test'테이블과 'gender_submission'테이블을 결합한다는 의미이다. 그리고, 그 결합한 것의 투플 수 (row 수)를 세는 코드이다.
두 테이블 다 418개의 투플을 갖고 있기 때문에, 이 결과도 418이 나온다.
CREATE TABLE `titanic` (
`PassengerId` int not NULL,
`Pclass` int NULL,
`Name` text,
`Sex` text,
`Age` double,
`SibSp` int NULL,
`Parch` int NULL,
`Ticket` text,
`Fare` double,
`Cabin` text,
`Embarked` text,
`Survived` int ,
primary key (`PassengerId` )
) ENGINE=InnoDB;
'titanic'이라는 테이블을 생성했다. 이 테이블에는 'test'테이블과 'gender_submission'테이블을 결합하여 저장할 것이다.
INSERT INTO `kaggle`.`titanic`
(`PassengerId`,
`Pclass`,
`Name`,
`Sex`,
`Age`,
`SibSp`,
`Parch`,
`Ticket`,
`Fare`,
`Cabin`,
`Embarked`,
`Survived`)
SELECT
A.`PassengerId`,
`Pclass`,
`Name`,
`Sex`,
`Age`,
`SibSp`,
`Parch`,
`Ticket`,
`Fare`,
`Cabin`,
`Embarked`,
B.`Survived`
FROM test A JOIN gender_submission B ON A.PassengerId = B.PassengerId ;
insert into, select, from join on 함수를 이용하여,
'test'테이블의 PassengerId값과 'gender_submission'테이블의 PassengerId값이 같을 경우,
두 테이블을 결합하여 각각의 값들을 'titanic' 테이블에 저장해 하나의 테이블로 만드는 것이다.
SELECT COUNT(*) FROM `kaggle`.`titanic` ;
'titanic' 테이블의 투플 수를 보여준다.
'gender_submission'의 'PassengerId'값은 외래키로, 'test' 테이블의 값을 참조한 것이기 때문에 모든 값이 같다.
따라서 모든 투플이 결합하여 저장되었기 때문에 count 수는 동일하게 418이다.
SELECT * FROM `kaggle`.`titanic` ;
'titanic' 테이블의 모든 값을 보여준다.
SELECT MAX(`Age`) FROM `kaggle`.`titanic`;
MAX함수는 이 속성에서 가장 큰 값을 보여준다.
SELECT MIN(`Age`) FROM `kaggle`.`titanic` WHERE `Age` > 0;
MIN함수는 반대로 이 속성에서 가장 크기가 작은 값을 보여준다.
WHERE은 조건문 느낌으로, 'Age'값이 0보다 큰 범위에서 가장 작은 값을 보여달라는 의미이다.
NULL값이 0으로 변환되었기 때문에 이 조건을 추가한 것이다.
SELECT AVG(`Age`), COUNT(*) FROM `kaggle`.`titanic` WHERE `Age` > 0;
AVG는 평균을 보여주는 값이다.
COUNT는 뒤에 WHERE `Age` > 0 의 조건이 붙었기 때문에 'Age' 값이 0보다 큰 투플의 개수를 알려준다.
SELECT sum(`Fare`) FROM `kaggle`.`titanic`;
sum은 해당 속성의 투플 값들을 모두 더한 값을 반환한다.
SELECT `Name`, `Pclass`, `Sex`, `Age` FROM `kaggle`.`titanic` ORDER BY 1 ;
ORDER BY 1은 SELECT 뒤에 나열된 4개의 속성들 중 첫번째 속성을 기준으로 오름차순 정렬하여 반환하라는 의미이다.
SELECT `Name`, `Pclass`, `Sex`, `Age` FROM `kaggle`.`titanic` ORDER BY 3 ;
마찬가지로 3번째 속성인 'Sex'를 기준으로 오름차순 정렬하라는 의미이다.
SELECT `Name`, `Pclass`, `Sex`, `Age` FROM `kaggle`.`titanic` ORDER BY `Name` DESC ;
ORDER BY - DESC는 해당 속성 기준으로 내림차순 정렬하라는 의미이다.
그리고 ORDER BY 뒤에 숫자보다는 이와 같이 속성명을 직접 써주는 것이 더욱 직관적이다.
SELECT * FROM `kaggle`.`titanic` WHERE `Name` LIKE 'A%' LIMIT 10;
LIKE 'A%' 은 'Name' 값들 중에서 A로 시작하는 값을 반환하라는 조건이다.
LIMIT 10은 그 중에서 상위 10개만 반환하라는 조건이다. 아마 조건에 대한 오름차순 정렬 후 10개인 것 같다.
SELECT DISTINCT `PassengerId` FROM `kaggle`.`titanic`;
DISTINCT 는 해당 속성의 값들 중 유일한 값만 조회하는 함수이다.
'PassengerId'의 경우 기본키로, 모든 투플이 유일하게 갖는 값이기 때문에 모든 값이 반환된다.
SELECT DISTINCT `Sex` FROM `kaggle`.`titanic`;
마찬가지로 'Sex' 의 값들 중 유일한 값들만 반환한다.
이 경우 투플 값이 male과 female 두 가지로 나뉘기 때문에 두개의 값만 반환된다.
SELECT `Sex`, COUNT(*) FROM `kaggle`.`titanic` GROUP BY 1;
GROUP BY는 해당 속성 값들을 그룹화하는 함수이다. 이 경우 'Sex'는 male과 female의 두개의 그룹으로 나뉠 것이다.
여기에 COUNT함수를 적용하면, 각각의 그룹에 속하는 투플 수를 보여준다.
SELECT `Sex`, COUNT(*) CNT FROM `kaggle`.`titanic` GROUP BY `Sex` HAVING CNT > 200;
위의 코드처럼 'Sex' 속성을 그룹화하여 count한 뒤, HAVING (조건) 을 이용해서 count값이 200보다 큰 값만 출력되도록 하는 코드이다.
count값을 CNT로 지정해서 HAVING 조건을 이용한 것이 특징이다.
위의 결과를 보면 male은 count값이 266, female은 152이기 때문에 male의 값만 출력되었다.
SELECT `Sex`, `survived`, COUNT(*) FROM `kaggle`.`titanic` GROUP BY `Sex`, `Survived` ;
'Sex' 속성과 'survived' 속성을 각각 그룹화하여 count값을 출력하는 코드이다.
이 값을 보면 남자는 모두 생존하지 못했고, 여자는 모두 생존했음을 알 수 있다.
SELECT floor(`Age`/10) * 10 + 10, COUNT(*) FROM `kaggle`.`titanic` WHERE `Age` > 0 group by 1;
floor는 반올림을 해주는 함수이다. 연령대별로 몇 명의 사람이 있는지 알아보기 위해서 'Age'를 10으로 나눈 값을 반올림하고, 10을 곱한 뒤, 0~9의 값이 있기 때문에 10을 더해준다. 그러면 이 값 미만의 사람들이 몇 명있는지 알아볼 수 있다.
SELECT floor(`Age`/10) * 10 + 10, COUNT(*) FROM `kaggle`.`titanic` WHERE `Age` > 0 group by 1 order by 1;
위의 값들을 오름차순으로 정렬하는 코드이다.
SELECT floor(`Age`/10) * 10 + 10, COUNT(*) FROM `kaggle`.`titanic` WHERE `Age` > 0 group by 1 order by 1 desc;
위의 값들을 내림차순으로 정렬하는 코드이다.
SELECT floor(`Age`/10) * 10 + 10, `survived`, COUNT(*) CNT FROM `kaggle`.`titanic`
WHERE `Age` > 0 group by 1, 1 HAVING CNT > 40 order by 1 desc, 2 desc;
위의 코드처럼 'Age'를 연령대 별로 나누고, 그 중 count값이 40보다 큰 값에 대해 'Age' 값과 'survived' 값을 각각 내림차순으로 정렬하는 코드이다.
#서브쿼리: 하나의 SQL문 안에 들어있는 또 다른 SQL문(쿼리)! 괄호( )로 나타낸다.
#서브쿼리가 조건절이 됨. 결과에 해당하는 데이터를 조건으로 해서 메인쿼리 실행.
SELECT * FROM `kaggle`.`titanic`
WHERE `PassengerId` IN (SELECT `PassengerId` FROM `test` WHERE `Age` = 0);
서브쿼리// 'test' 테이블에서 'Age'값이 0인 'PassengerId'를 찾는다.
메인쿼리// 그 'PassengerId'를 가진 값의 모든 데이터를 출력한다. ('PassengerId'가 JOIN으로 연결되어있기 때문에 같은 값임)
UPDATE `kaggle`.`titanic`
SET `Age` = 30.272590361445783
WHERE `PassengerId` IN (SELECT `PassengerId` FROM `test` WHERE `Age` = 0) ;
위의 코드대로 'Age' 값이 0인 데이터를 찾아서 그 값들의 'Age' 값을 평균인 30.272590361445783로 업데이트하는 코드이다.
업데이트한 후 위의 코드를 다시 실행시켜보면 'Age' 값이 모두 변경된 것을 볼 수 있다.
위의 코드는 'test' 테이블에서 'Age' 값이 0인 투플을 찾은 것이기 때문에 'titanic' 테이블에서 값을 변경한 뒤 다시 확인하기에 좋았다.