728x90

MySQL 주소에서 지역명 정리하기



DB 데이터 지역명이 서울특별시, 부산광역시 등으로 길게 나오는 경우보다 간략하게 서울, 부산으로 표기되도록 하는게 검색하는데 좀더 편하다.

아래 SQL문은 DB에 저장된 데이터에 지역명을 간략하게 업데이트 하는 명령어다.


SELECT * FROM addr_data WHERE addr0 LIKE '서울%';
SELECT * FROM addr_data WHERE addr0 LIKE '서울특별시%';
update addr_data set addr0=replace(addr0,'서울특별시','서울');
update addr_data set addr0=replace(addr0,'경기도','경기');
update addr_data set addr0=replace(addr0,'강원도','강원');
update addr_data set addr0=replace(addr0,'경상북도','경북');
update addr_data set addr0=replace(addr0,'경상남도','경남');
update addr_data set addr0=replace(addr0,'충청북도','충북');
update addr_data set addr0=replace(addr0,'충청남도','충남');
update addr_data set addr0=replace(addr0,'전라북도','전북');
update addr_data set addr0=replace(addr0,'전라남도','전남');
update addr_data set addr0=replace(addr0,'제주도','제주');
update addr_data set addr0=replace(addr0,'인천광역시','인천');
update addr_data set addr0=replace(addr0,'대전광역시','대전');
update addr_data set addr0=replace(addr0,'부산광역시','부산');
update addr_data set addr0=replace(addr0,'대구광역시','대구');
update addr_data set addr0=replace(addr0,'광주광역시','광주');
update addr_data set addr0=replace(addr0,'울산광역시','울산');
update addr_data set addr0=replace(addr0,'세종특별자치','세종');




'SQL' 카테고리의 다른 글

MySQL 운영 문제점과 해법들  (0) 2015.01.31
[SQL] 쿼리(Query)의 개념  (0) 2015.01.26
[오라클] 테이블 생성/변경시 제약조건  (0) 2015.01.23
MySQL 날짜, 통화이력 산출  (0) 2015.01.20
[MySQL] 데이터베이스 생성  (0) 2015.01.18
블로그 이미지

Link2Me

,
728x90

[오라클] 테이블 생성/변경시 제약조건(Constraint)


테이블을 생성/변경할 때 제약조건을 설정할 수가 있으며, 제약조건이란 테이블의 해당칼럼에 올바른 데이터만 입력받고 잘못된 데이터는 들어오지 못하도록 정하는 규칙이다.

- 제약조건은 테이블 Level 및 컬럼 Level 에서 규칙을 적용한다.

- 제약조건은 종속성이 존재할 경우 게시물 삭제를 방지한다.

- 테이블에서 행이 삽입, 갱신, 삭제될 때마다 테이블에서 규칙을 적용한다.

- 테이블 생성과 동시에 지정할 수도 있고, 테이블 생성 후에 추가할 수도 있다.

- 제약조건은 user_constraints 데이터 딕셔너리에서 검색할 수 있다.


제약조건의 종류


 조건 이름

의 미 

 NOT NULL

 조건이 설정된 칼럼에는 NULL 값이 입력되지 못한다 

  - 컬럼 Level 에서만 지정 가능

 Primary Key

 테이블당 1개만 설정 가능하며, 보통 자동으로 인덱스를 부여한다.

 NOT NULL + Unique 의 의미 

 중간 레코드(행)을 삭제해도 신규로 삭제되는 값은 Max(no) + 1 이다.

 Unique

 조건이 설정된 칼럼에는 중복된 값이 입력되지 못한다. 

  - NULL 값 저장 가능

  - 복합 칼럼 지정시에는 테이블 Level 에서만 가능

 Foreign Key

 다른 테이블의 칼럼을 참조해서 무결성 검사를 한다. 

 - ON Delete Cascade : 제약조건에 의해 참조되는 테이블(부모테이블)의 행이 삭제되면
   해당 행을 참조하는 테이블(자식테이블)의 행도 같이 삭제되도록 한다.
 - ON Delete Set NULL : 제약조건에 의해 참조되는 테이블(부모테이블)의 행이 삭제되면
   해당 행을 참조하는 테이블(자식테이블)의 행을 NULL 로 설정한다.

 Check

 이 조건으로 설정된 값만 입력을 허용하고 나머지는 거부된다. 


제약조건 정의 방법

1. 테이블 Level 지정 방법

   - 테이블 칼럼 정의와는 별개로 정의한다.

   - NOT NULL 제약조건을 제외한 모든 제약조건 정의가 가능하다.

2. 칼럼 Level 지정방법

   - 한개의 칼럼에 한개의 제약조건만 정의 가능하다.

   - 모든 제약조건 정의 가능하다.



블로그 이미지

Link2Me

,
728x90

통화이력 산출 SQL


최근 한달동안 통화이력이 없는 전화번호 현황을 출력하고 싶다면 어떻게 해야 할까?


 Oracle

  select 전화번호,날짜,요일

  from 전화번호 not in (

  select distinct 전화번호 from 통화이력 where 날짜 > sysdate -31

  );

 MySQL

  select 전화번호,날짜,요일

  from 전화번호 not in (

  select distinct 전화번호 from 통화이력 where 날짜 > (date_add(now(), interval -31 day)

  );


where 날짜 >= date_add(now(), interval -1 month) -- 한달전
where 날짜 >= date_add(now(), interval -1 day) -- 하루전
where 날짜 >= date_add(now(), interval -1 hour) -- 한시간전
where date_format(D_time,"%Y-%m-%d") = current_date; -- 오늘날짜인 거 가져오기
where D_time > date_sub(now(), interval 1 day); -- 등록된지 24시간이 안된 거



SELECT TO_DAYS('2015-01-20') - TO_DAYS('2014-11-15' ) AS "날짜차이";


SELECT now(), hour(now())as "시간" , minute(now()) as "분", second(now()) as "초", curdate(), curtime();


SELECT WEEKDAY(CURDATE()), WEEKDAY('2015-11-12');

0=월요일,1=화요일,2=수요일,3=목요일,4=금요일,5=토요일,6=일요일을 의미한다.


# 1일 추가하기
SELECT DATE_ADD(NOW(),INTERVAL 1 DAY);

# 한달 더하기
SELECT DATE_ADD(NOW(),INTERVAL 1 MONTH);
 

블로그 이미지

Link2Me

,
728x90


테이블을 생성하고 자료를 업로드할 때 자료에 한글이 있을 경우 깨지지 않게 처리를 하려면 인코딩 타입을 잘 맞춰줘야 한다.


mysql> show variables like '%char%';  -- character set 현황 조회

mysql> set character_set_server=utf8;  -- character set 변경

mysql> set character_set_database=utf8; -- character set 변경


mysql> create database work default character set utf8 collate utf8_general_ci;  -- 데이터베이스 생성

mysql> show databases;  -- 데이터베이스 보기


생성된 데이터베이스로 접속

mysql> use work;  -- 데이터베이스 접속


데이터베이스를 생성할 때 가장 편하게 하는 방법은 툴을 이용하는 방법이다.

phpMyAdmin 을 이용하여 데이터베이스를 백업하고 몇가지 툴 기능을 이용해보자.






위와 같이 설정하면 테이블 구조만 백업된다.

EditPlus 로 열어보니....



로 테이블 구조가 만들어져 있었다.

처음에 테이블 만들 때 Engine=MyISAM 으로 설정하지 않아서 InnoDB 로 만들어져 있었나 보다.


이 테이블 구조에서 테이블명을 변경하고 필요한 칼럼 등을 수정하고 나서

phpMyAdmin 에 복사하여 붙여넣기를 하면 손쉽게 테이블이 생성된다.


테이블명을 test_exercise 라고 변경하고 나서 한번 올려보자.



테이블이 생성된 것을 확인할 수 있다.


간단한 테이블 생성은 phpMyAdmin 을 이용하면 쉽게 해결할 수 있다.



블로그 이미지

Link2Me

,
728x90

MySQL 특정 칼럼의 행 비교후 개수 카운트


테이블을 정렬하여 테이블을 새로 생성하여 만든 테이블이 test_sort 테이블이다.



테이블의 특정 칼럼(serviceNo)이 중복된 값을 가지고 있다. 중복된 숫자를 카운트로 좀 나타내고 싶다.

어떻게 해야 할까?


결론부터 얘기하지면 아래 모습으로 결과를 얻고 싶다.

위아래 칼럼이 서로 같은 경우 개수를 증가하게 표시를 하고 싶다.



select uid, Name, serviceNo, if(serviceNo=@serviceNo_prev,@rownum:=@rownum+1,@rownum:=1) as checking, openDate, closeDate, (@serviceNo_prev:=serviceNo) as serviceNo_prev from test_sort limit 20;

일단 전부를 다 표시하는 것보다 20개만 발췌하여 결과값을 얻고 싶었다.


checking 이란 칼럼은 실제 test_sort 테이블에는 존재하지 않는 칼럼이라는 것은 위의 그림에서 확인할 수 있다.

그럼 이런 결과를 도출할 수 있을까?

사용자변수를 이용하여 1행, 2행, 3행 이렇게 비교를 하는 것이다.


SELECT / FROM / WHERE 구조의 의미는 다 아는 것이지만 다시 한번 살펴보자.

가장 먼저 FROM 테이블명에서 값을 가져오고, 그 다음에 WHERE 에서 조건에 맞는 것만 가져온다.

그 다음에 SELECT 구문에서 조회(출력)한다.

1행에서 @serviceNo_prev:=serviceNo 에는 serviceNo 값을 할당한다.

하지만 if(serviceNo=@serviceNo_prev,@rownum:=@rownum+1,@rownum:=1)이 먼저 실행된다.

@serviceNo_prev 라는 사용자변수에는 값이 할당되지 않았다.

따라서 첫행에서는 값이 서로다르다. 따라서 @rownum:=1 이 선택된다.

2행에서는 if(serviceNo=@serviceNo_prev,@rownum:=@rownum+1,@rownum:=1)

2행의 serviceNo 값과 @serviceNo_prev 에는 1행의 serviceNo 를 할당했으므로 서로 동일하다.

따라서 @rownum:=@rownum+1 즉, 2가 된다.


이런 식으로 처리하여 행간에 값을 비교하여 checking 칼럼을 생성한다.


그런데 보여주고자 하는 값이 uid, Name, serviceNo, checking, openDate, closeDate 이고 serviceNo_prev 는 아니라고 하면 어떻게 해야 할까?



윗 그림 전체를 임시테이블로 생각하면 된다. 즉 실제 물리적인 테이블에 저장된 것이라고 보고

테이블에서 원하는 필드만 조회(출력)해서 보여주면 된다.


select uid, Name, serviceNo, checking, openDate, closeDate from (select uid, Name, serviceNo, if(serviceNo=@serviceNo_prev,@rownum:=@rownum+1,@rownum:=1) as checking, openDate, closeDate, (@serviceNo_prev:=serviceNo) as serviceNo_prev from test_sort limit 20) a;


이렇게 이해하면 쉽게 이해가 될 것이다.



/* 테이블 구조만 복사 */

CREATE TABLE `생성될 테이블명` LIKE `구조를 복사할 테이블`;


/* 구조와 내용을 복사 */

CREATE TABLE `생성될 테이블명` AS SELECT * FROM `구조를 복사할 테이블`;


테이블 구조만 복사해서 새로운 테이블을 생성해보자.



테이블 구조에 필요한 칼럼이 하나 빠져있다. checking 칼럼을 추가한다.

- 지정 칼럼 뒤에 : ALTER TABLE 테이블명 ADD COLUMN 칼럼명 칼럼타입 AFTER 칼럼이름
- 제일 앞에        : ALTER TABLE 테이블명 ADD COLUMN 칼럼명 칼럼타입 FIRST
- 마지막에 추가  : ALTER TABLE 테이블명 ADD COLUMN 칼럼명 칼럼타입


칼럼 type 이 default 가 NULL 이라서 default 를 1로 변경하고자 한다.

/* 컬럼 타입 수정 */
alter table 테이블명 modify 컬럼명 varchar(14);
alter table test_fin modify checking int(2) not null default '1';



alter table test_fin modify checking tinyint(1) not null default '1';

공간을 가장 작게 차지하는 tinyint 로 변경해봤다.


이제 새로 만든 테이블에 위에서 작업한 내용을 복사해서 테이브를 집어넣어 보자.


INSERT INTO 테이블명 (칼럼1, 칼럼2, ...)

SELECT 구문


을 사용하면 된다.


insert into test_fin (uid, Name, serviceNo, checking, openDate, closeDate)
select uid, Name, serviceNo, checking, openDate, closeDate from (select uid, Name, serviceNo, if(serviceNo=@serviceNo_prev,@rownum:=@rownum+1,@rownum:=1) as checking, openDate, closeDate, (@serviceNo_prev:=serviceNo) as serviceNo_prev from test_sort) a;


제대로 데이터가 입력되었는지 확인해보니 정상적으로 입력되었다.


테이블 작업을 해서 새로운 테이블에 칼럼을 추가한 결과를 저정했다.


위 작업을 하면서 결과가 제대로 나오기 위해서는 EditPlus 에서 내용을 입력한 후 한줄로 처리한 다음에 복사하여 붙여넣기를 할 경우에만 정상적으로 값이 나왔다.

두줄로 분리하여 작업을 한 경우에는 사용자변수가 제대로 처리가 안되었다.



'SQL' 카테고리의 다른 글

MySQL 날짜, 통화이력 산출  (0) 2015.01.20
[MySQL] 데이터베이스 생성  (0) 2015.01.18
MySQL 테이블 칼럼 삭제  (0) 2015.01.16
MySQL 문자셋과 콜레이션이 쿼리에 미치는 영향  (0) 2015.01.16
MySQL 사용자 정의 변수  (0) 2015.01.13
블로그 이미지

Link2Me

,

MySQL 테이블 칼럼 삭제

SQL 2015. 1. 16. 00:44
728x90

테이블 칼럼을 삭제해야 할 경우가 있다.

이럴 때 사용하는 명령어는


alter table 테이블명 drop [column];


예제를 통해 테이블 칼럼이 삭제되었는지 확인해보자.



블로그 이미지

Link2Me

,
728x90

테이블 설계시에 character set 과 콜레이션은 신중하게 골라야 한다.

데이터베이스에서 문자셋을 섞어 쓰면 엉망이 된다.

특정 문자가 데이터에 나타나기 전까진 잘 동작하다가 어느 시점에 문제가 발생하기 시작한다.


character set 과 콜레이션을 상호 변환하는 일은 일부 연산에 오버헤드를 더한다.

일부 character set 은 CPU 연산이 더 필요하고, 메모리와 저장공간을 더 소비하며,

심한 경우 indexing을 무용지물로 만들기도 한다.


오류를 해결하려면 ALTER TABLE 을 이용해 문자셋을 변경해야 한다.

ALTER DATABASE DB명 DEFAULT CHARACTER SET utf8;
ALTER TABLE 테이블명 DEFAULT CHARACTER SET utf8;   -- utf8 대신 euckr 로 설정도 가능


DATABASE와 TABLE 생성시 CHARACTER SET 을 생락하면 기본값을 가져가게 된다.
DATABASE는 my.ini의 설정값을 기본값으로 갖고, TABLE은 DATABASE의 설정값을 기본값으로 갖게 된다.

두개의 테이블을 다른 character set을 가진 문자 칼럼에 대해 조인한다면,

MySQL 은 그중 하나를 변환해야 한다. 변환은 인덱스를 무용지물로 만들기도 하는데,

변환이 칼럼을 감싸는 함수와 같기 때문에 인덱스 적용이 안된다.


multibyte character set 에서는 문자 1개의 길이가 1byte가 아니다.

multibyte character set 을 다룰 땐 char_length() 함수를 써서 문자의 개수를 세야 한다.


select uid, char_length(kor) from mail_data where char_length(kor) > 50;


경고(warnings)가 발생하면 show warnings; 로 경고 내용을 확인해 보는게 좋다.


default character set 으로 utf-8 로 지정하면 편하다.

한글을 utf-8 로 지정하면 한 글자당 3bytes 를 차지한다.

영문은 utf-8 로 지정하면 한 글자당 1byte 를 차지한다. (저장공간 낭비 안함)

블로그 이미지

Link2Me

,

MySQL 사용자 정의 변수

SQL 2015. 1. 13. 07:29
728x90

MySQL 사용자 정의 변수


MySQL에서 하나의 명령문에 있는 값을 다른 명령문으로 전달하는 것이 가능하다.

사용자 정의 변수에 값을 저장한 후에 나중에 그 값을 참조할 수 있다.

한 클라이언트에서 정의된 사용자 변수는 다른 클라이언트에서는 보이지 않으며 사용할 수 없다. 

해당 커넥션에서 정의된 모든 변수는 클라이언트가 종료되면 자동으로 해제된다.


사용자 변수는 @var_name 이라고 쓰며, 항상 @ 하나가 따라와야 한다.

사용자 변수 이름은 알파벳, 숫자, ‘.’, ‘_’, 그리고 ‘$’을 사용할 수 있다.


사용자 변수 값 할당 방법

SET @var_name = expr  (정수, 실수, 문자열, NULL) SET 변수할당은 = 또는 := 둘다 사용 가능하다.

비 SET 문에서는 := 로 할당한다. = 는 비교 연산자로 취급되기 때문이다.

여러개의 변수를 선언할때는 DECLARE @ 변수명 자료형, @변수명 자료형

과 같은 방법으로 계속 적어주면 된다


SELECT 문의 가장 기본은 SELECT/FROM/WHERE이다. 

복잡한 쿼리문을 작성할 때도 SELECT/FROM/WHERE를 작성하고 나머지 부분을 채우는 것이 좋다


SET @rownum = 0;

select (@rownum := @rownum + 1) as No, name, email from emp order by name DESC;


SET을 지정하지 않고 한번에 처리하려면

select (@rownum := @rownum + 1) as No, e.name, e.email from (selct @rownum := 0) dummy, emp e order by e.name DESC;


No 를 지정하면 순차적으로 번호가 증가되어 결과를 찾을 때 좀더 편할 것이다.

from 절에서 조인(join) 으로 사용한 emp 테이블의 별칭을 e 로 지정했는데 select 문에서 e.name, e.email 등과 같이 명확하게 해주면 좋지만 그냥 name, email 로 적어도 무방하다.



참조

http://www.mysqlkorea.com/sub.html?mcode=manual&scode=01&m_no=21582&cat1=9&cat2=292&cat3=0&lang=k


블로그 이미지

Link2Me

,
728x90

텍스트 자료를 분석하기 위해서 MySQL DB에 저장하는 방법이다.

텍스트 자료를 DB에 저장하기 위해서는 한글의 경우 Encoding 모드(character set)가 서로 일치해야 한다.

MySQL DB 에 테이블을 생성할 때부터

업로드할 텍스트자료의 형식을 일치시켜 줘야 한다.


가장 먼저 DB character set 설정이 어떻게 되어 있는지부터 확인한다.

mysql> show variables like '%char%';  -- character set 정보 조회




character set 이 UTF-8 로 설정되어 있는 것을 확인할 수 있다.

만약 이 설정값이 latin1 으로 되어 있다면, my.cnf 에서 변경해줘야 한다.

변경을 해줬다면 데몬을 재실행하여야 한다.


character set 설정 상태를 확인했다면 이제 DB 를 생성해보자.


mysql> create database work default character set utf8 collate utf8_general_ci; 
mysql> show databases;  -- 데이터베이스 보기


DB를 생성하고 나서는
mysql> use work; 로 생성된 DB로 접속한다.
다음으로는 자료를 업로드할 테이블을 생성해야 한다.

  ※ 테이블을 생성하는 방법은 phpmyadmin 을 이용해서 생성해도 되고, 오라클 사이트에서 제공하는

      MySQL Workbench 라는 툴을 이용하거나, Toad for MySQL 을 이용해도 된다.

      테이블 생성은 보통은 EditPlus 와 같은 텍스트 툴을 이용하여 만든 다음에 복사하여 붙여넣기하면 편하다.


PC에 있는 텍스트 자료를 업로드하는 방법은

FTP 를 이용하여 서버상에 파일을 업로드한다.

만약 MySQL DB가 PC상에 설치된 DB라면 폴더명만 지정해주면 된다.


LOAD DATA INFILE '등록할 파일명'

INTO TABLE 등록될_테이블명
FIELDS TERMINATED BY '컬럼구분자'
LINES TERMINATED BY '\r\n'
 IGNORE 1 LINES
 (등록될_테이블명_컬럼1, 등록될_테이블명_컬럼2, ...);


만약 파일의 크기가 크고 테이블에 index가 걸려 있으면 시간이 굉장히 오래 걸릴 수 있다.

그럴 경우에는 아래와 같이 index를 먼저 해제해 주고 파일을 올린 다음 다시 index를 걸면 상당히 빠르게 테이블에 데이터를 넣을 수 있다.

mysql> ALTER TABLE dbName.tableName DISABLE KEYS;


읽어들일 파일명 경로를 지정하고 읽어들인다.


           ※ 경고가 발생했다. 테이블 설계시 칼럼 크기가 잘못된 것이 있다는 발견


테이블을 삭제하고 테이블을 다시 생성했다.


load data local infile '/home/test/test_text.csv'
into table `test`
fields terminated by ';'  -- 칼럼을 구분할 구분자를 지정
lines terminated by '\r\n'   -- Row(행)을 구분해줄 구분자를 지정
ignore 1 lines     -- 등록할 파일의 첫줄을 무시하고 등록하라
 (`Name` ,
  `serviceNo`  ,
  `openDate` ,
  `closeDate`
); 


    ※ -- 표시는 주석을 의미하며, 위 쿼리문을 복사해서 텍스트에 저장하고 필요한 부분만 수정 이용


그런데 이번에도 경고가 나와서 SELECT 문으로 조회를 해봤다.

앗!! Name 에 한글명이 나와야 하는데 없다.. 아뿔싸 파일명을 FTP 업로드할 때 Encoding Mode 를 ANSI 에서 UTF-8 로 변경해서 올리지 않았던 거다.



테이블을 삭제했으니 테이블 데이터만 비워야겠다.

mysql> truncate table 테이블명; -- 테이블 자체를 Drop 후 테이블 새로 생성 (DELETE 로 지운 것보다 훨씬 빠름)
mysql> truncate table test;



테이블을 비우고 나서 Encoding Mode를 UTF-8 로 변경해서 파일을 다시 업로드하고 나서 아래 명령어로 대용량 데이터를 DB로 업로드했다.



이제 정상적으로 한글명칭이 보인다. 성공


mysql> ALTER TABLE dbName.tableName ENABLE KEYS;


OPTIMIZE TABLE 테이블명 : 대량의 데이터를 삭제했던가, 테이블의 잦은 변화가 있을 경우 사용하면 유용하다.
대부분의 경우 ,OPTIMIZE TABLE 를 실행할 필요는 없다.
가변장 레코드에 갱신을 많이 실시하는 경우에서도 , 주 또는 달에 한 번 , 특정의 테이블인 만큼 실행하는 것만으로 충분하다.
삭제된 레코드는 링크된 리스트에 보관 유지되어 원의 레코드 위치는 , 후속의 INSERT 조작에 의해 재이용된다.
OPTIMIZE TABLE 을 사용해 미사용 영역을 해제해, 데이터 파일을 최적화할 수가 있다.


1.39 sec 는 최적화가 되어 있는 상태로 보면 된다.


저장할 디렉토리가 /usr/local/apache/htdocs/sql_backup/ 라고 가정하고 파일을 저장해보자.

디렉토리에는 쓰기권한이 설정되어 있어야 한다.

SELECT * INTO OUTFILE '/usr/local/apache/htdocs/sql_backup/memberfile.txt' FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' FROM member;

로 하면 텍스트 형태의 파일로 저장된 것을 확인할 수 있다.

블로그 이미지

Link2Me

,
728x90

대용량 테이블을 운용하는 경우 도움이 될만한 아티클 "Ten ways to improve the performance of large tables in MySQL"이 있어, 이 블로그에 정리해 봅니다.
아래 가지 10가지 방법을 잘 고민해 보면 좋은 도움을 받을 수 있을 것 같습니다.

오늘은 성능 문제를 일으키는 원인이 되는 대용량 테이블의 성능을 개선하는 방법을 살펴본다. 여기의 조언들은 일부는 많은 테이블을 가진 큰 데이터베이스에 적용할 수 있지만 대부분의 경우는 개별적으로 특별히 큰 테이블이 더 큰 문제라는 것이다.

테이블의 내용 변경의 속도는 테이블 사이즈가 커질수록 줄어드는 것을 일반적으로 알려진 사실이다. 아래는 B+Tree 인덱스의 성능을 시계열로 보여주는 그래프이다.



위의 그래프는 MySQL@Facebook에서 포스팅한 것이다. 이것은 insert buffer를 해제한 상태(물론 추천 하지는 않고, 데모 목적)에서 테이블에 10억 행을 insert했을 때의 성능 저하를 나타낸 것이다. 이 벤치 마크는 iibench 도구를 사용했고, TokuTek에서 디자인한 것이다.

그래서 우리는 이러한 성능 저하가 인덱스 구조에 의한 것이라고 생각했지만, 그래도 우리는 이 곡선을 급격하게 내려가지 않고, 옆으로 길게 늘어지도록 할 수 있는 방법을 모색해 봐야 한다.

대용량 테이블의 성능에 영향을 줄일 수 있는 10가지 방법

1.
MyISAM 대신에 InnoDB를 사용하자. MyISAM은 테이블의 마지막에 insert하는 경우에는 속도가 빠르지만, 테이블 잠금(update 및 delete에 제한 되지만)이 있고, 데이터를 디스크에서 읽기와 쓰기를 할 때 경합 때문에 키 버퍼를 보호하기 위해 싱글락을 사용한다. 또한 후술하겠지만, 체인지 버퍼 기능을 가지고 있지 않다.


2.
InnoDB는 유니크하지 않은 보조 인덱스의 빌딩을 지연시키는 체인지 버퍼 기능(이전에 insert buffer라고 불리던 기능)을 가지고 있다. 이에 대한 자세한 것은 Facebook의
노트에 기술되어 있다. 이것은 위의 그래프에는 보여지지 않지만, insert의 성능을 상당히 빠르게하는 것으로, 기본적으로 활성화되어 있다. 이 기능은 MySQL 5.5에서 좋게 개선 되었기 때문에, 만약 업그레이드 하지 않는 경우에는 즉시하는 것이 좋다.

3.
파티셔닝은 인덱스의 크기를 작게하여 테이블 자체를 효율적으로 작게 나눌 수 있게 된다. 또한, MySQL 5.7.2 DMR에서 상당히 개선된 내부적인 인덱스 잠금(
index->lock) 경합(contention)도 줄여 준다.

4.
InnoDB의
압축 기능을 사용하자. 몇몇 부하 종류의(특별히 많은 char/varchar/text형 컬럼이있는 경우) 압축 기능은 데이터를 압축해 성능 저하의 곡선을 완만하게 해준다. 또한, 일반적으로 용량이 작은 SSD를 사용해도 된다. InnoDB의 압축 기능은 Facebook에서 제공한 여러가지 패치 덕택에 MySQL 5.6에서는 크게 개선 되었다.

5.
정렬후 대용량의 데이터를 테이블에 로드해라. 정렬된 데이터를 인서트하는 것은, 페이지 분할(메모리 상에 없는 테이블에서 성능은 악화되는)이 작게 될 것이고, 대용량 데이터의 로드는 테이블의 용량과는 특별히 관계가 없지만, redo 로그의 압축 부하를 줄여주는데 도움을 준다.


6.
테이블에서 불필요한 인덱스를 지우자. 체인지 버퍼 기능을 비활성화시키는 UNIQUE 키를 특히 주의하자. 제약 조건을 사용할 이유가 없는 경우, UNIQUE 키를 사용하지 않고 일반적인 INDEX를 사용하자.


7.
5, 6에서 관련된 PRIMARY KEY의 종류도 중요하다. 성능 저하를 빠르게 만들어버리는 GUID와 같은 데이터 타입보다, INT나 BIGINT를 사용하자. PRIMERY KEY가 없는 것도 성능에 부정적인 영향을 준다.


8.
새 테이블에 대용량 데이터를 로드할 경우 PRIMARY KEY가 아닌 인덱스는 나중에 만들자. 모든 데이터가 로드된 후 인덱스를 만든다면, InnoDB는 pre-sort와 및 대용량 로드 프로세스(빠르고 인덱스가 좀 더 콤팩트한 인덱스를 만드는)를 적용 할 수 있게 된다. 이 최적화는 MySQL 5.5에서 이루어졌다.


9.
메모리가 많으면 많을수록 도움을 받을 수 있다. 최근의 메모리의 실제 가격을 비교해 보면 새로운 데이터 베이스 서버에 너무 적은 메모리를 적용하는 것을 자주 볼 수 있다. 간단한 조언을 해 보면, SHOW ENGINE INNODB STATUS의 결과에서 BUFFER POOL AND MEMORY의 reads/s의 보여주고(읽고 있음을 나타냄), Free buffers(이것도 BUFFER POOL AND MEMORY 아래에 있다)의 수가 0이면 메모리를 더 늘리면 혜택이 얻을 수 있다.(innodb_buffer_pool_size를 잘 최적화했다는 가정하에.
이 문서를 참고).

10.
메모리 뿐만 아니라, SSD도 도움이 된다. 그래프의 곡선이 하향이 되는 이유는 테이블이 커져서 일어나는 IO 속성 때문이다. 하드 디스크가 초당 200 오퍼레이션(IOPS)을 수행하는데 반해, 일반적인 SSD는 20000 IOPS 이상 수행이 가능하다.


용어 정의

  • Change Buffer: MySQL 5.5이전에는 insert buffer라고 했으며, 이름 그대로 INSERT의 성능을 향상시키기 위한 버퍼다. insert buffer는 새로운 행을 삽입하는 INSERT에 대해서만 유효했는데, Change Buffer는 UPDATE 및 DELETE도 좋은 효율성을 보여준다.


출처 : http://www.mimul.com/pebble/default/2013/12/07/1386399914136.html

블로그 이미지

Link2Me

,
728x90

특정 게시물 앞, 뒤 레코드값 출력


MySQL에서 원하는 게시물 앞뒤 5개를 출력하고 싶어서 MySQl 쿼리문을 날려봤다.

결과가 어떻게 나오는지 달라진다.

이전 : SELECT * FROM 테이블 WHERE 필드 < 번호 ORDER BY 필드 DESC LIMIT 5;
해당 : SELECT * FROM 테이블 WHERE 필드 = 번호;
이후 : SELECT * FROM 테이블 WHERE 필드 > 번호 ORDER BY 필드 LIMIT 5;



이걸 연결해서 출력하고 싶어서 오라클 전문가에게 도움을 청해서 도움을 받아서 실행을 해봤다.



출력하고자 하는 uid 값이 제대로 출력이 되었다.


select uid from (
 select * from TABLE_NAME where uid = 10
 union
 select * from (select * from TABLE_NAME where uid > 10 order by uid asc limit 5 ) a
 union
 select * from (select * from TABLE_NAME where uid < 10 order by uid desc limit 5 ) b
 ) c order by uid;

select uid 대신에 select name, email 등과 같은 칼럼을 직접 지정해주면 원하는 것만 결과를 뽑아낼 수가 있다.


만약 PHP 게시판에서 찾는 검색조건에 이걸 넣고 싶다면 어떻게 해야 할까?

보통 검색 조건은 $sqlque .= " and ".$where." like '%".trim($keyword)."%'";

로 되어 있다.

이 경우에는 IN 조건으로 찾으면 된다.

$sqlque .= " and uid IN (select uid from ( select * from ".TABLE_NAME." where uid = '".trim($keyword)."'
 union
 select * from (select * from ".TABLE_NAME." where uid > '".trim($keyword)."' order by uid asc limit 5 ) a
 union
 select * from (select * from ".TABLE_NAME." where uid < '".trim($keyword)."' order by uid desc limit 5 ) b
 ) c order by uid " ;



블로그 이미지

Link2Me

,
728x90

SYSDBA 접속 및 User 생성, 권한부여



ORACLE DB에 접속하려면, 먼저 USER를 생성하고 DBA의 권한을 부여해야 한다.
오라클을 설치 완료했다면, RUN SQL Command Lind 프롬프트를 실행해 보자.


CMD 도스창 모드에서

(1) sysdba 접속
sysdba 계정으로 먼저 로그인한다. 비밀번호는 오라클 설치시에 설정한 비밀번호이다.

sqlplus sys/oracle as sysdba



(2) User 생성
이제 새로운 User를 생성해 보자.
일반적으로 학습용 DBA의 아이디 비밀번호는 SCOTT / TIGER 를 설정한다.
연습할 User 와 비밀번호는 user01 / user01 로 설정한다.


SQL> create user user01 identified by user01;   -- 사용자 할당 및 비밀번호 생성

SQL> grant connect, resource, dba to user01;    -- 접속권한 부여



(3) user01 접속

이제 user01 로 접속해보자.

sqlplus user01/user01



(4) 테이블 업로드

실습할 SQL 파일을 읽어서 DB에 저장하기 위해서

C:\temp 폴더에 script_v2.0.sql 파일을 복사한다.

SQL> @c:\temp\script_v2.0.sql;   -- 파일에서 불러오기



(5) 사용자 비밀번호 변경

SQL> alter user user01 identified by tiger;    -- user01 사용자의 비밀번호를 tiger 로 변경









블로그 이미지

Link2Me

,
728x90

[오라클] SQL 실습을 위한 오라클 11g 설치


오라클에서 회원가입만 하면 누구든지 오라클 SQL를 다운로드 받아 설치해서 연습해볼 수 있게 제공하고 있으니 부담없이 다운로드 받아 설치해보자.


설치를 위해서는 총 3개의 파일이 필요하다.

1. JDK 설치

2. 오라클 DB 설치

3. 오라클 SQL Developer


[JDK 설치]

http://java.oracle.com 에 접속한다.




자신의 운영체제에 맞는 걸 선택해서 다운로드 받은 다음에 설치하면 된다.

설치시 특별한 설명이 필요한 것이 없으니 설치과정은 생략한다.



[Oracle DBMS 설치]

데이터베이스(DBMS) 중에서 가장 안정성이 높아서 기업에서 많이 사용하는 오라클 데이터 베이스 설치를 하려면 http://www.oracle.com/kr/index.html 에 접속하여 회원가입을 한다.



로그인할 때 비밀번호는 대문자를 1글자 넣어야 된다. 회원 아이디 생성할 때 비밀번호에 대문자, 숫자가 들어간다는 걸 기억하고 있어야....

보통 대문자 설정을 잘 안하는데 오라클, 아이폰 사이트 로그인할 때는 비밀번호에 대문자가 들어간다.


다운로드를 누르고 oracle 11g를 선택하면 http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html 로 접속된다.




약간 아래로 내리면 오라클 데이터베이스 11g release 2 가 보인다.

본인 PC에 맞는 운영체제에 따라 파일 2개(File1, File2) 를 내려받는다.




다운로드 받은 2개의 파일을 압축을 풀면 아래의 형태로 보일 것이다.

setup 을 눌러서 설치한다.



전자메일 입력란에 보안관련 알림을 받기 위한 사용자 email을 입력한다.
‘My Oracle Support를 통해 보안 갱신 수신’ 체크박스는 해제하고 [다음] 버튼을 선택한다



프록시 서버 설정창이 나오면 ‘구성 상의 중요 보안문제에 대한 알림을 수신하지 않습니다’ 체크박스를 선택하고 [계속] 버튼을 선택한다.


설치 옵션은 ‘데이터베이스 생성 및 구성’을 선택하고 ‘다음’ 버튼을 선택한다


데스크톱 클래스’를 선택하고 [다음] 버튼을 선택 한다.


전역 데이타베이스 이름은 orcl 로 설정한다. 다른 이름으로 변경하고 싶다면 변경해도 된다.

그리고 설치할 드라이브를 C로 변경하고 싶다면 Oracle Base 에서 D를 C로 변경만 해주면 자동으로 변경된다.




중간에 오류가 나는 경우가 있다. 이 경우에는 모두 무시를 선택하고 설치했더니 이상없이 설치가 잘 되었다.

설치 확인을 위해서 PC와 노트북에서 모두 설치를 해봤다. 노트북에서 에러가 나서 모두 무시하고 설치를 했다.



설치하는 과정에 시간이 좀 걸린다.

설치가 다 되고 나면 비밀번호 관리를 눌러서 비밀번호 설정을 해준다.



연습할 대상 DB 테이블 접속을 위해서 사용자 비밀번호 지정을 해줘야 한다.

scott 계정에 잠금설정을 해제하고 새로운 비밀번호를 scott 로 입력해도 좋고 tiger 로 입력해도 좋다.

본인이 원하는 비밀번호를 설정하면 된다.





설치가 다 되면 닫기를 눌러준다.


설정이 다 끝났으면 접속은 다음 글에서 접속하면 된다.



[ 오라클 Developer 다운로드]

오라클 Developer 를 다운로드 받으면 SQL 명령문 연습을 편하게 할 수 있다.

다운로드만 하고 실행파일만 실행하면 별도의 설치없이 이용이 가능하다.


http://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html




본인 PC 운영체제에 맞는 버전을 받으면 된다.

혹시라도 접속에 문제가 된다면 이전 버전을 받는다.


다운로드 받아서 원하는 폴더에 압축을 풀고나서 실행파일만 실행해주면 된다.


접속을 하기 위해서는 아래 그림과 같은 순서로 관리자 접속을 위한 설정을 해준다.

비밀번호는 DBMS 설치하면서 설정한 비밀번호 (ex, oracle) 를 입력한다.

그리고 정상적으로 접속되는지 확인한 다음에 저장한다.




이제 scott 계정 접속을 설정한다.




user01 계정 생성하는 방법이다.

여기서 직접 등록해도 되고 다음 게시물에서처럼 등록해도 된다.



이제 접속 설정을 위한 준비는 다 끝났다.




이제 열심히 SQL 명령문을 연습해보고 이해하자.












블로그 이미지

Link2Me

,

SQL 서브쿼리

SQL 2014. 12. 19. 00:30
728x90


문법 : 

SELECT   select_list

FROM   table 또는 view

WHERE  조건   연산자  ( SELECT  select_list

      FROM  table

     WHERE  조건  ) ;



sub query 는 메인 쿼리 안에 포함되어  있는 또다른 별도 Select 문이다.

여러번의 Select문을 수행해야 얻을 수 있는 결과를 하나의 중첩된 Select 문으로 쉽게 얻을 수 있다.

sub query 가 먼저 실행되고, 그 결과가 메인 쿼리에 전달되어 실행된다.

두개의 테이블을 sub query 로 조인할 때에는 반드시 일치되는 공통 칼럼을 사용해야 한다.

- sub query 는 Select문의 select 절, FROM 절, Where절, Having 절에 올 수 있다.

  . select 절에 오는 sub query 는 스칼라 서브쿼리,

  . FROM 절에 오는 서브쿼리는 inline view 서브쿼리

- sub query 는 SELECT 문만 아니라 다른 문(INSERT, DELETE, UPDATE) 에도 쓸 수 있다

- sub query 에는 반드시 괄호를 사용한다.

- operator(연산자) 는 단일행 연산자 ( > , = , >= , < , <= , != )와

                              복수행 연산자 ( IN , ANY ,ALL,EXISTS )를 사용 할 수 있다.

- 단일행 sub query : sub query 의 결과가 1개의 행만 나오며, 반드시 단일행 연산자를 사용해야 한다. 

- 복수행 sub query : sub query 가 여러 개의 행을 리턴하며, 반드시 복수행 연산자를 사용해야 한다.
- sub query 에는 order by 를 사용할 수 없다.
-
sub query 에는 NULL 값이 있으면 결과가 출력되지 않는다.


예제

단일행 sub query


-- 1. EMP 테이블에서 'SCOTT' 보다 급여를 많이 받는 사람의 이름과 급여를 출력


SQL> select ename, sal
from emp
where sal > (select sal from emp where ename = 'SCOTT');

-- 2. 사원테이블에서 BLAKE 보다 급여가 많은 사원들의 사번, 이름, 급여 출력
SQL> select empno, ename, sal
from emp
where sal > (select sal from emp where ename ='BLAKE');


-- 3. 사원테이블에서 MILLER 보다 늦게 입사한 사원의 사번, 이름, 입사일을 검색
SQL> select empno, ename, hiredate
from emp
where hiredate > (select hiredate from emp where ename = 'MILLER');
select hiredate from emp where ename = 'MILLER';


-- 4. emp 테이블에서 사원번호가 7521의 업무와 같고 급여가 7934 보다 많은 사원의 사원번호, 이름, 담당업무, 입사일자, 급여를 출력
SQL> select empno, ename, job, hiredate, sal
from emp
where job = (select job from emp where empno=7521)
and sal > (select sal from emp where empno = 7934);


-- 5. 서브쿼리에서 그룹함수 사용
select empno, ename, job, sal, deptno
from emp
where sal < (select avg(sal) from emp);

-- 6. 사원테이블에서 사원 전체 평균 급여보다 급여가 많은 사원들의 사번, 이름, 급여를 검색
SQL> select empno, ename, sal
from emp
where sal > (select avg(sal) from emp);


-- 7. emp 테이블에서 20번 부서의 최소급여보다 많은 모든 부서의 최소급여 출력

--  having 절에서의 서브쿼리

SQL> select deptno, min(sal)
from emp
group by deptno
having min(sal) > (select min(sal) from emp where deptno = 20);


복수행 sub query
- 복수행 서브쿼리 : IN, ALL, ANY
- 복수행 서브쿼리란 sub query 의 결과가 2건 이상 출력되는 것을 말한다.

- 메인 쿼리의 비교 조건이 sub query 의 결과 중에서 하나라도 일치하면 검색 가능

-- 1. emp 테이블에서 업무별로 최소 급여를 받는 사원의 사원번호, 이름, 업무, 입사일자, 급여, 부서번호 출력
SQL> select empno, ename, job, hiredate, sal, deptno
from emp
where sal IN (select min(sal) from emp group by job)

order by 3;

-- 2. 사원테이블에서 업무가 MANAGER인 사원의 최소급여보다 적은 급여를 받는 사원들의 이름 검색
SQL> select empno, ename, job, sal, deptno
from emp
where sal < ALL (select sal from emp where job = 'MANAGER');

-- ALL 을 사용한 것과 min(sal)을 사용한 것이 결과는 동일하다.
SQL> select empno, ename, job, sal, deptno
from emp
where sal < (select min(sal) from emp where job = 'MANAGER');

-- 3. ANY : 최소값보다 큰, ALL : 최소값보다 작은
SQL> select empno, ename, job, sal, deptno
from emp
where sal > ANY (select sal from emp where job = 'MANAGER');

SQL> select empno, ename, job, sal, deptno
from emp
where sal > (select min(sal) from emp where job = 'MANAGER');

-- 4. EXISTS 연산자 : sub query 에서 검색된 결과가 하나라도 존재하면 메인 쿼리 조건이 참이 되는 연산

-- 사원중에서 comm 을 받은 사원이 한 명이라도 있으면 모든 사원 출력
SQL> select *
from emp 
where exists (select empno from emp where comm IS NOT NULL);

다중컬럼 서브쿼리 : pairwise (컬럼을 쌍으로 묶어서 동시에 비교하는 방식)

-- sub query 에서 여러 개의 컬럼 값을 검색하여 메인 쿼리의 조건절과 비교하는 sub query

--5-1. 사원테이블에서 부서별로 가장 많은 급여를 받는 사번, 이름, 이메일, 급여 출력

-- 부서별 : group by 를 사용해야 한다는 의미, 최대 급여 : max(sal)
SQL> select deptno, empno, ename, sal
from emp
where (deptno, sal) IN (select deptno, max(sal) from emp group by deptno);

다중컬럼 서브쿼리 : unpairwise (칼럼별로 나누어 비교하고 나중에 AND 연산 처리하는 방식)

--5-2. 사원테이블에서 부서별로 가장 많은 급여를 받는 사번, 이름, 이메일, 급여 출력
SQL> select deptno, empno, ename, sal
from emp
where deptno in (select deptno from emp group by deptno)
and sal in (select max(sal) from emp group by deptno);

-- 6. 사원테이블에서 부서별 최대 급여를 받는 사원들의 사번, 이름, 부서코드, 급여를 검색

-- 오류가 생길 수 있는 쿼리문
SQL> select empno, ename, deptno, sal
from emp
where sal in (select max(sal) from emp group by deptno);


-- 정확한 쿼리문
select empno, ename, deptno, sal
from emp
where (deptno, sal) in (select deptno, max(sal) from emp group by deptno);

블로그 이미지

Link2Me

,
728x90

SQL 그룹함수, having절


단일 행 함수와는 달리 그룹 함수는 여러 행 또는 테이블 전체에 대해 함수가 적용되어 하나의 결과를 가져오는 함수이다.

그룹 당 하나의 결과가 주어지도록 행의 집합에 대해 연산할 경우 GROUP BY절을 이용하여 그룹화 할 수 있고 HAVING를 이용하여 그룹에 대한 조건을 제한할 수 있다


기본구문은 아래와 같다.
SELECT column_name, group_function(column_name)
FROM table_name
WHERE column_name =  'value'  -- where 절에는 그룹함수가 올 수 없음
GROUP BY column_name
-- group by 절 뒤에는 컬럼 별칭을 사용할 수 없음


- GROUP BY 절은 데이터들을 원하는 그룹으로 나눌 수 있다.

- 나누고자 하는 그룹의 컬럼명을 SELECT절과 GROUP BY절 뒤에 추가하면 된다.

- 그룹함수를 사용하여 특정 그룹으로 구분할 때는 GROUP BY 절을 사용하며, 특정 그룹없이 중복된 데이터를 제거할 경우에는 DISTINCT 절을 사용한다.

- Count(*) 함수는 서로 다른 모든 행에 대하여 연산하지 않고 각 그룹화된 행에서 계산된다.


그룹함수의 종류

Count : NULL 이 아닌 행의 개수

SUM : NULL 값을 제외한 입력 데이터들의 합계

AVG : NULL 값을 제외한 입력 데이터들의 평균

MAX : 입력 데이터들의 최대 값

MIN : 입력 데이터들의 최소 값

STDDEV : NULL 값을 제외한 입력 데이터들의 표준편차

VARIANCE : NULL 값을 제외한입력 데이터들의 분산 값



예제


-- 각 부서별로 인원수, 급여의 평균, 최저 급여, 최고 급여, 급여의 합을 구하여 급여의 합이 많은 순으로 출력

SQL> SELECT deptno, count(*), round(avg(sal),0), min(sal), max(sal), sum(sal)
FROM emp
GROUP BY deptno
ORDER BY sum(sal) desc;


-- 업무별로 그룹하여 업무, 인원수, 평균 급여액, 최고 급여액, 최저 급여액 및 합계를 조회
SELECT job, COUNT(empno) "인원수", round(AVG(sal)) "평균급여액", MAX(sal) "최고급여액",
       MIN(sal) "최저급여액", SUM(sal) "급여합계"
  FROM emp
  GROUP BY job;





SELECT deptno, ename, AVG(sal)
FROM emp
GROUP BY deptno;
위 구문은 정상적인 결과를 조회할까?
※ 그룹함수 사용시 GROUP BY 절로 묶이지 않은 단순 컬럼은 SELECT 리스트에 사용 불가능하고 사용시 에러가 발생한다. 정상적으로 처리되려면 SELECT 문에서 ename 을 제거하던가, 아니면 GROUP BY 문에 ename을 추가하던지 해야 한다.

SELECT deptno, ename, AVG(sal)
FROM emp
GROUP BY deptno, ename;


HAVING 절
SELECT COUNT(column) as cnt FROM table GROUP BY column HAVING COUNT(column) > 5;
  - WHERE 절에서는 집계함수를 사용 할 수 없다.
  - HAVING 절은 집계함수를 가지고 조건비교를 할 때 사용한다.
  - HAVING절은 GROUP BY절과 함께 사용된다.

-- 사원수가 다섯 명이 넘는 부서와 사원수를 조회
SELECT d.dname, COUNT(e.empno) "사원수"
 FROM emp e, dept d
 WHERE e.deptno = d.deptno
 GROUP BY d.dname
 HAVING COUNT(e.empno) > 5;


ANSI 조인으로 표기하면....

SELECT d.dname, COUNT(e.empno) "사원수"
 FROM emp e INNER JOIN dept d
 ON e.deptno = d.deptno
 GROUP BY d.dname
 HAVING COUNT(e.empno) > 5;

-- 전체 월급이 4000을 초과하는 job에 대해서 job과 월급여 합계를 조회.
-- 단 판매원(SALESMAN)은 제외하고 월 급여 합계로 내림차순 정렬
SELECT job, SUM(sal) "급여 합계"
 FROM emp
 WHERE job != 'SALESMAN'          -- 판매원은 제외
 GROUP BY job                    -- 업무별로 Group By
 HAVING SUM(sal) > 4000     -- 전체 월급이 4000을 초과하는
 ORDER BY SUM(sal) DESC;   -- 월급여 합계로 내림차순 정렬

분석 :
먼저 직업별로 조회해본다. select job from emp group by job;
그러면 직업 전체 현황이 조회된다. 판매원을 뜻하는 job 이 뭔지 정확하게 파악할 수 있다.
비교조건이 월급이다.
SUM(sal) > 4000 을 초과하는 job 을 조회하라는 것인데
where 조건에는 그룹함수 SUM(sal) 을 사용하여 비교할 수가 없으므로 Having SUM(sal) 로 비교해야 한다.





**별 평균/합계가 2000 이상 과 같은 조건이 나오면 Group by Having 절을 사용한다고 기억하면 된다.


블로그 이미지

Link2Me

,

SQL 숫자함수 및 예제

SQL 2014. 12. 17. 07:42
728x90

SQL 숫자함수


Round(숫자, 원하는 자릿수) : 주어진 숫자를 반올림하여 출력함

SELECT ROUND(column_name,decimals) FROM table_name;

-- 급여가 1500부터 3000사이의 사람은 급여의 15%를 월회비로 지불
-- 출력양식은 이름, 급여, 회비(10원 단위는 반올림 처리) 정보를 출력
SQL> select ename, sal, round((sal*0.15),-2) 회비 from emp where sal between 1500 and 3000;
           회비  = sal * 0.15
           정수 2번째 자리에서 반올림 : 100 단위로 계산


Trunc(숫자, 원하는 자릿수) : 주어진 숫자를 버림한 후 출력함

오라클에서는 trunc 로 하면 되는데 MySQL 에서는 truncate 로 해야 한다.


-- 30번(영업부) 부서원의 연봉을 계산하여 이름, 부서번호, 급여, 연봉 정보를 연봉이 큰 순서데로 출력하라.

-- 연말 특별 보너스 150%, 연봉은 천단위 미만 절삭처리

SQL> select ename, deptno, sal ,trunc(((sal * 12) + (sal * 1.5)),-3) 연봉 from emp where deptno =30 order by 연봉 desc;


-- 급여(sal)가 2000 이상인 모든 사람은 급여의 5%를 경조비로 내기로 하였다 .
-- 이름, 급여, 수당(소수점이하 절삭 처리) 정보를 출력하라.
SQL> select ename as 이름, sal as 급여 , trunc((sal*0.05),0) 경조비 from emp where sal >= 2000;


MOD(숫자, 나누기할 수) : 주어진 숫자를 나누기 한 후 나머지 값 출력함



CEIL(숫자) : 주어진 숫자와 가장 근접한 큰 정수를 출력함

SQL> select ceil(10.7) from dual;



FLOOR(숫자) : 주어진 숫자와 가장 근접한 작은 정수를 출력함

SQL> select floor(10.7) from dual;



POWER : 제곱하여 출력함




SQL> select sign(1000), sign(0), sign(-22) from dual;




-- 예제 : 사원테이블에서 입사일이 12월인 사원의 사번, 사원명, 입사일 검색

-- 사원번호(empno), 사원명(ename), 직급(job), 관리자번호(mgr), 입사일(hiredate), 급여(sal),

-- 커미션(comm), 부서번호(deptno)
SQL> select empno, ename, hiredate from emp where to_char(hiredate,'MM')='12';





블로그 이미지

Link2Me

,
728x90

MYSQL 함수에 대한 기본적인 설명은 http://www.w3schools.com 에 가면 잘 나와 있다.

substr(string,start,length) : 문자열/칼럼에서 특정 길이를 추출할 때 사용하는 함수

substr 함수는 SQL, PHP, VBA 등에서 모두 같은 의미로 사용된다.


SQL> select substr(hiredate,1,6) from emp;

-- 첫번째부터 6개의 글자를 가져오라는 의미

PHP 문에서 주석처리는 //를 사용하는데, SQL 에서는 주석처리는 -- 를 붙인다.

VBA 에서는 주석처리는 ' 를 붙인다.


SQL> SELECT left(addr1,6) FROM member_data WHERE addr0 LIKE '서울%';

-- 지역이 서울인 주소(add1)에서 왼쪽에서부터 6글자를 잘라서 보여줘라


SQL> SELECT right(addr1, 6) FROM member_data WHERE addr0 LIKE '서울%';

-- 지역이 서울인 주소(add1)에서 오른쪽에서부터 6글자를 잘라서 보여줘라


  • $result = mysql_query("SELECT pub_name, SUBSTR(pub_name,4,5)  
  • FROM publisher  
  • WHERE country='USA'");  
  • while($row=mysql_fetch_array($result))  
  • {  
  • echo "<tr>";  
  • echo "<td align='center' width='200'>" . $row['pub_name'] . "</td>";  
  • echo "<td align='center' width='200'>" . $row['SUBSTR(pub_name,4,5)'] . "</td>";  
  • echo "</tr>";  
  • }  
  • echo "</table>";  
  • ?>  
  • - See more at: http://www.w3resource.com/mysql/string-functions/mysql-substr-function.php#sthash.nImc3OUs.dpuf
  • $result = mysql_query("SELECT pub_name, SUBSTR(pub_name,4,5)  
  • FROM publisher  
  • WHERE country='USA'");  
  • while($row=mysql_fetch_array($result))  
  • {  
  • echo "<tr>";  
  • echo "<td align='center' width='200'>" . $row['pub_name'] . "</td>";  
  • echo "<td align='center' width='200'>" . $row['SUBSTR(pub_name,4,5)'] . "</td>";  
  • echo "</tr>";  
  • }  
  • echo "</table>";  
  • ?>  
  • - See more at: http://www.w3resource.com/mysql/string-functions/mysql-substr-function.php#sthash.nImc3OUs.dpuf
  • $result = mysql_query("SELECT pub_name, SUBSTR(pub_name,5)   
  • FROM publisher   
  • WHERE country='USA'");  
  • while($row=mysql_fetch_array($result))  
  • {  
  • echo "<tr>";  
  • echo "<td align='center' width='200'>" . $row['pub_name'] . "</td>";  
  • echo "<td align='center' width='200'>" . $row['SUBSTR(pub_name,5)'] . "</td>";  
  • echo "</tr>";  
  • }  
  • echo "</table>";  
  • ?>  
  • - See more at: http://www.w3resource.com/mysql/string-functions/mysql-substr-function.php#sthash.nImc3OUs.dpuf

    <?php
    // MYSQL 데이터베이스를 연다
    $result = mysql_query("SELECT pub_name, SUBSTR(pub_name,4,5) FROM publisher WHERE country='USA'"); 
    while($row=mysql_fetch_array($result))

        echo "<tr>";
        echo "<td align='center' width='200'>" . $row['pub_name'] . "</td>"; 
        echo "<td align='center' width='200'>" . $row['SUBSTR(pub_name,4,5)'] . "</td>"; 
        echo "</tr>"; 

    echo "</table>";
    ?> 

    INSTR (string, 찾는글자, 시작위치) : 문자열/칼럼에서 특정 글자의 위치를 찾아주는 함수


    LPAD(문자열, 자릿수, '채울문자') : 원하는 문자열을 선행에 Padding

    -- LPAD(문자열, 자릿수, '채울문자')
    SQL> select empno, ename, LPAD(sal,10,'*') "급여" from emp;



    RPAD(문자열, 자릿수, '채울문자') : 원하는 문자열을 행에 Padding

    SQL> SELECT RPAD('dennis kim', 15, '*') NAME FROM dual ;


    LTRIM(문자열, '제거할문자')


    NVL(칼럼, 치환할 값) : NULL 값을 다른 값으로 바꾸어 주는 함수


    CONCAT(char1, char2) : Concatenation의 약자로 두 문자를 결합하는 역할을 하며 || 연산자와 같다.


    INITCAP(char)  : 주어진 문자열의 첫 번째 문자를 대문자로 변환시켜 준다

    -- MySQL 에서는 함수 지원을 못하는지 에러가 발생






















    블로그 이미지

    Link2Me

    ,
    728x90

    MySQL 테이블 이름변경, 삭제, 칼럼삭제, 칼럼추가


    MySQL 에서 테이블을 삭제하거나 이름 변경, 그리고 테이블의 칼럼을 삭제하거나 추가, 이름 변경하는 것에 대하 알아봤다.


    가장 편한 방법은 phpMyAdmin 을 이용하면 이런 작업이 수월한데 MySQL 자체에서도 어떻게 하는 것인지 알아두면 좋을 거 같아서 적어둔다.


    테이블 이름 변경
    mysql > RENAME TABLE `comnetlink`.`rb_member_data1` TO `comnetlink`.`rb_member_data` ;

    테이블 삭제
    mysql > DROP TABLE `rb_member_data`;

    테이블 칼럼 삭제
    mysql > ALTER TABLE `rb_member_data` DROP `is_modify`;

    mysql > ALTER TABLE `rb_member_data` DROP `is_checking`, DROP `is_modify`;

    테이블 칼럼 추가
    mysql > ALTER TABLE `rb_member_data` ADD `is_modify` TINYINT( 4 ) NOT NULL DEFAULT '0' AFTER `is_checking`;

    테이블 칼럼 이름 변경
    mysql > ALTER TABLE `rb_member_data` CHANGE `is_modify` `modify` TINYINT( 4 ) NOT NULL DEFAULT '0';

    'SQL' 카테고리의 다른 글

    SQL 숫자함수 및 예제  (0) 2014.12.17
    SQL 문자열 처리함수 instr, nvl, lpad 등  (0) 2014.12.16
    phpMyAdmin 을 이용한 테이블 등록  (0) 2014.12.01
    MySQL 통계 Group by  (0) 2014.11.30
    MySQL 인덱스  (0) 2014.11.25
    블로그 이미지

    Link2Me

    ,
    728x90

    phpMyAdmin 을 이용한 테이블 등록

    phpMyAdmin 을 이용하여 DB에 테이블을 등록하는 방법이다.

    오늘 실수로 테이블을 날려 먹었다.

    테이블을 백업 받아두고 날려 먹어서 다행이었지 정말 시껍했다.

    PHP 4.0 버전에서는 varchar(9) 길이가 짧아도 테이블에 긴 데이터가 들어가는 모양이다.

    PHP 5.6 버전에서는 이런 걸 칼같이 잡아내어 칼럼길이를 충분히 늘려주고 데이터를 업로드했다.



    블로그 이미지

    Link2Me

    ,

    MySQL 통계 Group by

    SQL 2014. 11. 30. 00:30
    728x90

    MySQL 통계 Group by


    문제 : 판매자별 상품 판매건수를 구하라.

    SQL 문 : Group by 문을 활용하고, 판매자 ID 별로 건수를 SUM하면 된다. 만약 테이블 레코드가 한줄씩 들어간 경우라면 SUM 대신에 Count(goods_code) 를 하면 된다.

    SELECT sales_name, SUM (goods_code)

    FROM orders

    GROUP BY sales_name;


    집계함수
    • COUNT : 행의 개수를 센다.
    • AVG : 행들의 값들을 평균낸다.
    • SUM : 행들의 값을 모두 더한다.
    • MAX : 최대값을 구한다.
    • MIN : 최소값을 구한다.
    • STDEV : 표준편차를 구한다.

    FROM 절에서 여러 개의 테이블 명세가 사용되는 경우에 가명(alias)를 사용하는 것이 더 편리할 때가 있다. 가명(alias)는 FROM 절에서 선언한다. 가명이 정의되면 다른 절에서 실제 테이블 이름 대신에 가명을 사용할 수가 있다.

    가명(alias)이 FROM 이 나오기 전에 SELECT 절에서 사용하지만 FROM 절이 먼저 처리되기 때문에 아무런 문제가 없다.
    가명(alias)은 256문자까지 사용 가능하며, 첫글자는 반드시 영문으로 시작해야 하고, 영문자, 숫자, 밑줄 문자를 사용할 수 있다.

    동일한 테이블을 이용해서 가명(alias)를 2개 사용하여 원하는 결과를 얻어야 하는 경우가 있다. 

    문제 : 홍길동 판매자보다 더 많은 상품을 판매한 사람을 출력(조회)
    분석 : 홍길동 판매자가 몇 건을 판매했는지를 알아야 한다는 점, 그리고 홍길동보다 판매건수가 더 많은 걸 구해야 한다는 점이다.
    SQL 코드 
    SELECT s.sales_name, s.goods_code FROM orders s, orders t WHERE t.sales_name = '홍길동' and s.goods_code > t.goods_code

    select Count(컬럼명) from 테이블명; // null 값은 카운트 하지 않는다
    select Count(Distinct 컬럼명) from 테이블명; // 중복된 데이터없이 카운트


    블로그 이미지

    Link2Me

    ,