예를 들어 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개의 속성들 중 첫번째 속성을 기준으로 오름차순 정렬하여 반환하라는 의미이다.
name 기준으로 오름차순 정렬된 것을 볼 수 있다
SELECT `Name`, `Pclass`, `Sex`, `Age` FROM `kaggle`.`titanic` ORDER BY 3 ;
마찬가지로 3번째 속성인 'Sex'를 기준으로 오름차순 정렬하라는 의미이다.
sex 기준으로 오름차순 정렬된 것을 볼 수 있다
SELECT `Name`, `Pclass`, `Sex`, `Age` FROM `kaggle`.`titanic` ORDER BY `Name` DESC ;
ORDER BY - DESC는 해당 속성 기준으로 내림차순 정렬하라는 의미이다.
그리고 ORDER BY 뒤에 숫자보다는 이와 같이 속성명을 직접 써주는 것이 더욱 직관적이다.
name 기준으로 내림차순 정렬된 것을 볼 수 있다
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' 테이블에서 값을 변경한 뒤 다시 확인하기에 좋았다.
unsigned는 부호가 없다는 뜻이다. 예를 들어 tinyint의 경우, (signed) tinyint의 범위는 -128~127이며,
unsigned tinyint의 범위는 0~255이다.
NULL, NOT NULL은 NULL값이 될 수 있냐 없냐를 정해주는 것이다. 예제의 경우 학번과 이름은 NULL값이 될 수 없도록 했다.
varchar( )의 괄호 속 숫자는 최대로 들어갈 수 있는 byte 값이다.
`leave_yn`는 휴학여부 속성으로 0과 1로 구분되고, 투플값이 없을 경우 default 값은 0이 들어가도록 했다.
`last_update`는 업데이트 시각으로, 직접 적는 것이 아니라 CURRNET_TIMESTAMP를 이용하여 자동으로 저장된다.
이 테이블의 기본키는 `student_id`로, 학번만 가지고도 투플들을 구분할 수 있다는 뜻이다.
MySQL의 스토리지 엔진으로 주로 MyISAM과 InnoDB가 사용된다.
스토리지 엔진은 데이터베이스 엔진이라고도 불리며, RDBMS가 데이터베이스에 대해 데이터를 삽입, 추출, 업데이트, 삭제하는 데 사용하는 기본 소프트웨어 컴포넌트이다.
MyISAM은 항상 테이블에 ROW COUNT를 가지고 있기 때문에 SELECT 명령 시 속도가 빠르고, '풀텍스트 인덱스'를 지원하는데, 이는 자연 언어를 이용해 검색할 수 있는 특별한 인덱스로 모든 데이터 문자열의 단어를 저장한다는 것이다. 이때문에 Read only 기능이 많은 서비스일수록 효율적으로 사용할 수 있는 엔진이다. 단점으로는, row level locking을 지원하지 못해서 select, insert, update, delete 명령 시 해당 테이블 전체에 locking이 걸린다는 것이다. 그래서 갱신이 많이 필요한 경우에는 유용하지 못하다.
InnoDB는 MyISAM과 대조적인 엔진으로, 우선 row level locking이 지원된다는 장점이 있고, 트랜잭션 처리가 필요한 대용량 데이터를 다룰 때 효율적이다. 데이터의 변화가 많은 서비스에 적합하다. 또한, 유일하게 외래키를 지원하는 표준적인 스토리지 엔진이다.단점으로는, 풀텍스트 인덱스를 지원하지 않는다는 것이 있다.
주로 InnoDB를 많이 사용한다고 하고, 이번 예제에서도 InnoDB를 사용하였다.
INSERT INTO `university`.`student` (student_id, name, address, birth_date, major_id, enterance_year, leave_yn) VALUES (2016001, '정소정', '서울시 서초구 방배동 911-1', '19971101', 111, 2016, 0), (2017053,'성민경','경상북도 대구 수성구 삼익 1-1','19980412',111,2017,1), (2018111,'노규희','충청남도','19991204',130,2018,1), (2017105,'박성희','강원도','19980908',130,2017,0);
student 테이블에 투플들을 삽입하는 코드이다.
INSERT INTO로 속성을 한 번 나열하고, VALUES를 통해 각각의 개체들을 추가한다.
select * from `university`.`student`;
select from은 테이블에서 정보를 가져온다는 뜻이고, *은 테이블에 있는 모든 데이터를 가져온다는 뜻이다.
따라서 이 코드를 실행하면 university.student에 있는 4개의 투플들을 보여준다.
select * from `university`.`student` where student_id = 2016001;
where은 조건의 개념으로, 이 경우에는 학번이 2016001인 투플의 모든 데이터를 가져온다는 뜻이 된다.
select student_id, name from `university`.`student` where major_id = 111;
이 경우에는 selcet student_id, name 이므로, 전공번호가 111인 투플의 학번과 이름을 가져온다.
UPDATE `university`.`student` SET address = '부산특별시 해운대 비치333-3', leave_yn = 1 WHERE student_id = 2016001;
update는 말 그대로 테이블을 새로운 정보로 업데이트한다는 뜻이다.
이 경우, 학번이 2016001인 투플의 주소와 휴학여부 정보를 변경하게 된다.
select * from university.student where student_id = 2016001;
DELETE FROM university.student WHERE student_id = 2016001;
select * from university.student where student_id = 2016001;
select * from university.student;
select문은 마찬가지로 정보를 가져오는 코드이고,
DELETE문은 university DB의 student 테이블에서 student_id가 2016001인 투플을 삭제하는 코드이다.
CREATE TABLE `university`.`class` ( `class_id` int unsigned NOT NULL , `name` varchar(20) NOT NULL , `professor_id` int NOT NULL , `major_id` smallint NULL , `duration` smallint NULL , `type` tinyint NULL , `start_time` char(2) NULL, `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (class_id) ) ENGINE = InnoDB;
두번째로 universityDB 안에 'class'라는 테이블을 생성한 것이다.
속성으로는 class_id, name, professor_id, major_id, duratin, type, start_time, last_update가 있고 각각의 도메인이 달려있다.
INSERT INTO `university`.`registerClass` (student_id, class_id) VALUES (2017053, 10000), (2017053, 50003);
resigterClass 테이블에 투플들을 생성하는 코드들이다.
코드를 보면 student_id와 class_id 투플값이 모두 student테이블의 student_id와 class테이블의 class_id에 있는 값들인 것을 확인할 수 있다. 외래키를 사용했기 때문이다.
#INSERT INTO `university`.`registerClass` #(student_id, class_id) #VALUES #(2017053, 45003);
이처럼 만약 참조되는 테이블에 없는 값을 value로 입력하면 오류가 뜬다.
SELECTS.NAME, C.NAME, R.last_update #조회할 것 -> 결합할 것 FROM student Sjoin registerClass Ron S.student_id = R.student_id #조건 join class Con R.class_id = C.class_id where S.student_id = 2017053;
SELECT S.NAME, C.NAME, R.last_update FROM student S join registerClass R on S.student_id = R.student_id join class C on R.class_id = C.class_id where S.student_id = 2018111;
SELECT S.NAME, C.NAME, R.last_update FROM student S join registerClass R on S.student_id = R.student_id join class C on R.class_id = C.class_id where S.student_id = 2017105;
join은 릴레이션 간의 조합을 검색하는 키워드이다.
예를 들어, 첫번째 예시는 학번이 2017053인 학생의 이름(from S)과 수강한 과목(C), 수강신청시간(R)을 조회하는 코드이다.
우선 join 다음에 나오는 on은 두 테이블이 결합할 조건을 의미한다.
이 예제에서는 student테이블의 student_id와 registerClass테이블의 student_id가 같을 경우,
student테이블의 name과 class테이블의 name과 registerClass테이블의 last_update를 결합한다는 의미이다.
객체는 사람, 자동차, 건물, 주문, 생산, 관리 등 눈에 보이거나 어떠한 행동을 나타내는 단어를 예로 들 수 있다.
반대의 개념은 절차 프로그래밍이 있는데,
이것은 순서대로 일어나는 일을 시간 순으로 프로그래밍하는 것으로, C언어가 대표적이다.
2. 클래스
클래스란 객체에 대한 속성과 기능을 코드로 구현한 것으로, 사용자 정의 자료형이라고 말할 수 있다.
클래스는 데이터와 함수로 정의된다.
예를 들어 "학생"이라는 클래스가 있다면,
데이터는 학번, 이름, 학년, 주소 등이 있고,
함수로는 수강신청, 수업 듣기, 시험 보기 등이 있을 것이다.
속성은 객체의 특성을 정의하는 것으로, 변수 또는 데이터, 멤버 변수라고도 부른다. (명사)
위의 예에서 학번, 이름, 학년, 주소 등이 해당된다.
함수는 메서드라고도 불리며, 객체가 하는 기능들을 구현하는 것이다. (동사)
3. 클래스 정의하기
(접근 제어자) class 클래스이름 {
멤버 변수;
메서드;
}
/* 클래스 이름은 대문자로 시작하며, 하나의 자바 파일에 하나의 클래스를 두는 것이 기본이다.
여러 개의 클래스가 같이 있는 경우, public 클래스는 단 하나이며, public 클래스와 자바 파일의 이름은 동일해야 한다.
자바의 모든 코드는 class 내부에 위치한다. */
<학생 클래스 만들기>
package classpart;
public class Student {
int studentId;
String studentName;
int grade;
String address;
public void showStudentInfo() {
Sysstem.out.println(studentName + ", " + address);
}
}
studentId부터 address까지가 멤버 변수이고,
public void showStudentInfo()가 학생 정보를 보여주는 기능을 하는 메서드(함수)이다.
4. 패키지
패키지란 클래스 파일의 묶음이다. 패키지를 만들면 프로젝트 하위에 물리적으로 디렉토리가 생성된다.
패키지는 계층 구조로 구성되며, ( . ) 온점으로 계층을 구분한다.
패키지명은 소문자로 적는다.
package 패키지명;
5. 메서드
메서드는 함수의 일종으로, 객체의 기능을 제공하기 위해 클래스 내부에 구현되는 함수이다.
함수란 하나의 기능을 수행하는 일련의 코드로, 중복되는 기능은 함수로 구현하여 함수를 호출하여 사용한다.
//함수 선언
int add (int num1, int num2) {
return num1 + num2;
}
//함수 사용
public void static main(String[] args) {
int sum = add(10, 20);
System.out.println("10 + 20 = " + sum);
}
<함수의 장점>
1) 기능을 나누어 코드를 효율적으로 구현할 수 있다.
2) 기능별로 함수를 구현해 놓으면 같은 기능을 매번 코드로 만들 필요가 없다.
3) 프로그램을 실행할 때 생긴 오류를 수정하는 디버깅 작업을 할 때도 편리하다.
**가능하면 하나의 함수에 하나의 기능만 구현하는 것이 좋다.
6. 객체 생성하기
클래스를 사용하기 위해서는 "객체"를 생성해야 한다.
new 예약어를 이용해 객체를 생성한다.
클래스명 변수이름 = new 생성자();
ex) Student studentA = new Student();
7. 생성자
생성자란 객체가 생성될 때 멤버 변수의 값을 초기화하기 위해 사용되는 특별한 함수를 말한다.
생성자 이름은 클래스명과 같다.
생성자는 메서드가 아니고, 상속되지 않으며, 리턴 값이 없지만 앞에 void를 적지 않는다.
디폴트 생성자는 객체가 생성될 때 컴파일러가 자동으로 생성하는 코드이다.
클래스에 생성자를 추가하면 디폴트 생성자는 제공되지 않는다.
8. 생성자 재정의 (오버로드)
함수명은 같고 전달되는 인자의 자료형이 다른 함수를 정의하면 이를 메서드 오버로드라고 부른다. 즉, 다른 함수로 취급된다.
이를 이용해 생성자의 초기화 함수를 여러 개 정의할 수 있다. 이때, 전달되는 인자의 자료형과 개수를 달리 해야한다.
public class Person {
String name;
float height;
float weight;
public Person() {} //디폴트 생성자
public Person(String pName) { //이름이 인자로 전달되는 생성자,
name = pName; //pName을 전달하여 멤버변수 name을 초기화할 수 있다.
}
}
9. 참조 자료형
변수의 자료형에는 기본 자료형과 참조 자료형이 있다.
ㅇ기본 자료형에는 앞서 포스팅한 것과 같이 boolean, char, short, int, long, float, double이 있으며,
참조 자료형에는 String, Student, Person 등이 있다.
참조 자료형은 클래스 형으로 선언하는 자료형을 의미한다.
예를 들어, 학생 클래스에 (학번, 이름, 국어 성적, 수학 성적, 수강 과목 이름)이 있다고 하자.
이때 수업에 대한 각 속성을 학생 클래스에 정의하지 않고, 수업이라는 클래스로 분리해서 사용하는 것이다.
그럼 과목은 참조 자료형으로 선언되어서 학생 클래스에서 사용될 수 있다.
10. 정보 은닉
클래스의 외부에서 클래스 내부의 멤버 변수나 메서드에 접근하지 못하게 하는 경우에 사용된다.
이를 통해 오류를 줄일 수 있다.
일반적인 경우에 멤버 변수는 private을 선언하여 외부에서 접근하지 못하게 하고,
메서드는 public으로 선언하여 외부에서도 사용할 수 있도록 한다.
그래서 멤버 변수를 외부에서 접근하지 않고 객체를 생성할 수 있도록 생성자를 사용한다.
또한, 생성자를 이용하면 객체를 한번에 초기화 할 수 있다.
package exercise.domain;
public class Student {
private int studentId;
private String name;
private int grade;
private String address;
public void courseRegistration() {
System.out.println("수강신청");
}
public void takeAClass() {
System.out.println("수업듣기");
}
public void takeATest() {
System.out.println("시험보기");
}
public void showStudentInfo() {
System.out.println(name + ", " + address);
System.out.println(studentId + ", " + grade);
}
//생성자
public Student (int pStudentId, String pName, int pGrade, String pAddress) {
studentId = pStudentId;
name = pName;
grade = pGrade;
address = pAddress;
}
}
package exercise.test;
import exercise.domain.Student;
public class StudentTest {
public static void main(String[] args) {
Student stu1 = new Student(1224, "홍길동", 1, "서울특별시"); //생성자 함수 호출
Student stu2 = new Student(1225, "이순신", 2, "충무로"); //-> 객체 한번에 초기화
//함수에서만 멤버 변수 접근하도록
stu1.showStudentInfo();
stu2.showStudentInfo(); //메서드 호출
**private 멤버 변수를 클래스 외부에서 접근할 때에는 get() / set() 메서드를 제공한다.
if (조건식1) { 수행문1; } else if (조건식2) { 수행문2; } else { 수행문3;
(예제)
int age = 9;
int charge = 0;
if (age < 8) {
charge = 1000;
System.out.println("미취학 아동입니다.");
} else if (age < 14) {
charge = 2000;
System.out.println("초등학생입니다.");
} else if (age < 20) {
charge = 2400;
System.out.println("중고등학생입니다.");
} else {
charge = 3000;
System.out.println("성인입니다.");
}
System.out.prinln("요금은 " + charge + "원 입니다.");
조건 연산자 (삼항 연산자)
간단한 if - else 조건문을 조건 연산자로 구현할 수 있다.
if (a > b) max = a; else max = b;
max = (a > b) ? a : b;
2) switch - case 문
조건식의 결과가 특정 정수 값 또는 특정 문자열 값과 같을 경우 사용한다.
case문에서 수행문이 끝나면 반드시 break; 를 써줘야 한다. 그렇지 않으면 break;를 만날 때까지 계속 아래의 수행문을 수행한다.
다음과 같이 여러 case를 한 번에 묶을 수도 있다.
(예제)
int month = 1;
int day = 0;
switch(month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
day = 31;
break;
case 2:
day = 28;
break;
case 4:
case 6:
case 9:
case 11:
day = 30;
break;
}
System.out.println("day = " + day);
final int Gold = 1;
final int Silver = 2;
final int Bronze = 3;
int medal = 1;
switch(medal) {
case Gold:
System.out.println("금메달입니다.");
break;
case Silver:
System.out.println("은메달입니다.");
break;
case Bronze:
System.out.println("동메달입니다.");
break;
default:
System.out.println("금메달입니다.");
}
위와 같이 마지막에 default를 써줄 수도 있다. 위의 case를 모두 만족하지 않으면 default의 수행문이 실행된다.
JAVA 버전 7부터는 case 값에 문자열을 사용할 수 있지만, 위의 예제처럼 웬만하면 숫자로 비교하는 것이 좋다.
2. 반복문
1) while 문
조건이 "참"인 동안 수행문을 반복해서 수행한다.
주로 조건식이 true, false로 나타난다.
while (조건식) {
수행문 1;
...
}
수행문2;
(예제)
int i = 0;
final int count = 10;
int sum = 0;
while (i <= count) {
sum += i;
++i;
}
System.out.println("1부터 " + count + "까지의 합 = " + sum);
2) do - while 문
먼저 수행문을 한 번 수행하고 조건식을 체크한다.
수행문이 반드시 한 번 수행되어야 하는 경우에 사용한다.
do {
수행문1;
...
} while (조건식);
수행문2;
(예제)
int i = 2;
do {
System.out.println(i);
++i;
} while (i < 1);
이 예제는 조건식이 처음부터 만족되지 않았지만, do 안에 있는 수행문은 한 번 실행된다.
3) for 문
가장 많이 사용되는 반복문으로, 주로 조건이 횟수인 경우에 사용한다.
for문 안에 초기식, 조건식, 증감식을 모두 쓰기 때문에 코드가 간결해질 수 있다.
for문 안에서만 쓰이는 변수는 초기식에서 선언과 초기화를 한번에 해주는 것이 좋다.
for (초기식 ; 조건식 ; 증감식) {
수행문1;
...
}
수행문2;
(예제)
for (int num = 1; num <= 5; num++) {
System.out.println(num);
}
for (int i = 1; i <= 9; i++) {
System.out.println(i + "단");
for (int j = 1; j <= 9; j++) {
System.out.println(i + "x" + j + "=" + i*j);
}
}
구구단 예제 코드이다.
int total = 0;
for (int i = 1; i <0 100; i++) {
if (i % 2 ==0) continue;
total += i;
System.out.println(total + "i = " i);
}
total = 0;
for (int i = 1; i <= 100; i++) {
if (i % 2 == 1) {
total += i;
System.out.println(total + "i = " i);
}
}
위의 예제에서 continue; 는 아래의 실행문을 실행하지 않고 증감식으로 넘어가라는 의미이다.
위의 for문과 아래의 for문은 100 이하의 홀수끼리만 더하라는 의미로 결과가 같은 코드이다.
int total = 0;
for (int i = 1; i <= 100; i++) {
if (i == 50) break;
total += i;
System.out.println(total + " i = " + i);
}
System.out.println("total = " + total);
위의 예제와 같이 for문에서 break; 를 쓰면 loop를 벗어난다. 즉, i가 50이 되면 그 이상 증가하지 않고 loop를 빠져나와서 아래의 print문을 실행하는 것이다.