-리눅스 디렉토리 설명---------------------------------------------------------------------
/━━━┳ usr (윈도우의 frogram files와 동일, {/usr/bin/ = 배치[PATH 변수]디렉토리, /bin/과 같다.})
┣ var (변경이 많은 프로그램 ex: Log, 메일)
┣ bin (배치[PATH 변수]디렉토리. DOS에서 AUTOEXEC.BAT 파일 안에 PATH설정을 해준것과 같다. 안에있는 파일들은 어디서든 실행된다.)
┣ root (최상 관리자 홈디렉토리)
┣ etc (각 시스템의 고유한 설정 파일)
┣ lib (공유 라이브러리 파일)
┣ dev (하드웨어 장치 파일)
┣ mnt (마운트를 하기위한 디렉토리. 일반적으로 CD-ROM, FLOPPY)
┣ tmp (임시 파일 공간.윈도우의 temp와 동일)
┣ proc (가상파일 시스템)
┣ home (유저 홈디렉토리)
┣ .
.
.

-계정, 도움말 관련 명령어---------------------------------------------------------------------------------------
man : 명령어 옵션이나 사용법들을 보여준다.(ex: man ls = ls라는 명령어의 사용법이나 옵션을 보여준다.)
which : PATH변수를 참조하여 명령어를 검색해준다.alias명령으로 단축지정된 것까지 보여준다.(which ls = ls 명령어가 있는 위치를 보여준다.)
whereis: 명령어를 검색해준다. which 명령보다 좀더 넓은 범위에서 메뉴얼 페이지 경로까지 검색해준다.

useradd : 유저계정을 생성한다.
userdel : (옵션: -r) 해당 계정뿐만 아니라 그 계정에 관련된 모든 디렉토리가 삭제된다..
usermod : 유저계정을 수정한다. /etc/passwd 파일을 직접 편집하는 방법도 있다.
groupadd : 그룹을 생성한다.
groupdel : 그룹을 삭제한다.
groupmod : 그룹을 수정한다. /etc/group 파일을 직접 편집하는 방법도 있다.
*계정을 생성하면 1개의 디렉토리 생성과 3개 파일에 정보가 추가된다.
1.새로만든 계정의 홈디렉토리 생성
2./etc/passwd 파일안에 정보 추가
3./etc/group 파일안에 정보 추가
4./etc/shadow 파일안에 정보 추가

chown : 파일에 대한 소유자나 그룹을 변경할수 있으며 오직 root만이 사용 가능하다.(ex: chown 오세헌.안양2동 /etc/root.sh = root.sh란 파일의 소유자는 오세헌 그룹은 안양2동으로 변경한다.)
(옵션: -R) 해당 디렉토리에 포함된 모든 파일과 하위 디렉토리의 소유자나 그룹을 변경할수 있다.
chgrp : 파일에 대한 소유그룹을 변경할수 있으며 오직 root만이 사용 가능하다.
(옵션: -R) 해당 디렉토리에 포함된 모든 파일과 하위 디렉토리의 소유그룹을 변경할수 있다.
chmod : 소유자, 그룹, 그외에 대해서 읽기, 쓰기, 실행 권한(퍼미션)을 설정할수 있다.
*퍼미션 부여방법
파일은 기본적으로 drwxrwxrwx 형식을 가진다.
-맨 앞의 d는 디렉토리를 뜻한다. 링크파일(바로가기)인 경우 l로 표시되며, 일반 파일일 경우는 -로 설정된다.
-맨처음 rwx는 소유자에 대해 읽기, 쓰기, 실행이 설정된 값이다. 공통적으로 r은 4, w는 2, x는 1로써 권한을 주고싶은 목록의 숫자를 다더한 값을 퍼미션으로 설정한다.
-두번째 rwx는 그룹에 대해 읽기, 쓰기, 실행이 설정된 값이다.
-세번째 rwx는 그외에 대해 읽기, 쓰기, 실행이 설정된 값이다.
(ex: chmod 700 aa = aa라는 파일에 대해 소유자만 읽기,쓰기,실행 권한을 갖도록 한다.)
(ex: chmod 751 aa = aa라는 파일에 대해 소유자는 읽기,쓰기,실행 권한을 가지고 그룹에 대해서는 읽기,실행 권한만을 가지며 그외에는 실행 권한만 갖도록 한다.


-프로세서 관련명령어--------------------------------------------------------------------------------
vi /etc/inittab : 부팅모드를 수정할수 있다. 1.치명적인 오류가 났을때,루트암호를 잊어버렸을때 3.디폴트(윈도우의 F8키 눌렀을때와 같다)
vi /etc/farad : 부팅할때 실행할 파일들을 설정한다.(윈도우의 시작프로그램과 동일)
vi /etc/fstab : 부팅할때 마운트할 파티션을 설정한다.
ntsysv : 부팅시 자동으로 실행되는 프로세스(데몬)들을 쉽게 설정 할수 있다.

w : 부팅한지 몇일(UPTIME)되었는지 확인(3계월 재부팅권장), 부하율 확인(2.0이하 권장)

top : 실시간으로 정보(CPU, MEMORY, 하드 스왑 사용률)를 보여준다.
(옵션: -d 1) 정보를 1초 단위로 갱신하여 실시간으로 보여준다.
* m을 누르면 메모리를 가장 많이 소모하는 파일 순으로 맨위에서부터 차례대로 보이게 된다.

ps : (옵션: -ef) 동작하고 있는 프로세스 목록을 보여줌. 대괄호([])가 쳐진 프로세스는 시스템 프로세스
(옵션: aux | more) 동작하고있는 프로세스의 부하율을 보여줌
%CPU = CPU부하율, %MAM = RAM(메모리)부하율

kill : (옵션: -9) 프로세서를 강제적으로 죽인다.

vi /etc/crontab : 매 정해진시간마다(주기적) 실행할 파일들을 설정한다.
* #run-parts 아래에다가 실행할 파일을 적어 넣는다.
* 형식: 분 시 일 달 요일 root run-parts 실행할 파일
(ex: 1 * * * * root run-parts /etc/OSH.conf = 매 1분마다 etc 디렉토리 안에 OSH.conf이라는 파일을 실행한다.)
(ex: */5 * * * * root run-parts /etc/you/OSH.conf = 매 5초마다 etc/you 디렉토리 안에 OSH.conf라는 파일을 실행한다.)
(ex: 0-59/3 * * * * root run-parts /etc/kiki.conf = 매 3초마다 etc 디렉토리 안에 kiki.conf이라는 파일을 실행한다.)

-네트워크 관련 명령어------------------------------------------------------------------------------------
netstat : (옵션: -na) 접속한 주소를 확인 →TCP에 관련된 것만 보임
(옵션: -lnp) 접속한 주소와 포트를 볼수있음(서비스를 대기하고있는 프로그램)
[/etc/hosts 에서 접속했던 IP를 따로 표시할수 있도록 설정 할수있음]
[SNMP프로토콜을 이용하여 netstat에서 나온 정보로 트래픽확인 가능→MRTG를 이용 그래픽모드로 볼수있음.]
*netstat -lnp를 하여 나온 포트 설명
:80 = http
:6666 = httpd - 아파치서버(웹서버)
:873 = 사용률이 적은 데몬을 묶어서 관리,실행하는 슈퍼서버 데몬(xinetd) - rsync(알싱크: 데이타 동기화 프로그램. 백업할때 사용)
:29999 = 결제 프로그램
:783 = 펄(안티 프로그램). 스팸 어세신 프로그램
:7766 = 결제 프로그램(데몬)
:21 = proftpd - FTP
:22 = sshd - ssh
:23 = 사용률이 적은 데몬을 묶어서 관리,실행하는 슈퍼서버 데몬(xinetd) -telnet
:25 = sendmail
:5051 = 시스템 메니저먼트 서버(SMS). 서버의 상태를 알려줌.(zagent) /tcp, udp
:199 = snmpd - 네트워크 메니저먼트 시스템(NMS). 트래픽 모니터링을 할때 필요한 프로토콜.(snmp) /tcp
:161 = snmpd - 네트워크 메니저먼트 시스템(NMS). 트래픽 모니터링을 할때 필요한 프로토콜.(snmp) /udp
:110 = 사용률이 적은 데몬을 묶어서 관리,실행하는 슈퍼서버 데몬(xinetd) -pop3
:53 DNS /udp,tcp
:3306 my-sql /tcp
:3389 telminal /tcp
:8080 = httpsd - 웹기반 설치를 위한 setting
0.0.0.0 = 80포트로 실행하면 전부다 접속 가능
127.0.0.1 = 외부에서 접속 불능
*데몬에는 독립실행형데몬(자주쓰는 프로세서)과 슈퍼서버데몬(자주쓰지않는데몬의 집합)이 있다. 프로세서 마다 메모리를 소모하기 때문에 잘 실행하지않는 데몬들을 묶어서 하나의 데몬처럼 유지하면서 프로세서가 실행할 때마다 슈퍼서버 데몬(xinetd)이 관리 실행토록하여 메모리관리를 효율적으로 해준다.
*tcp는 3way handsh 6, udp는 17또는 11, icmp 1

host : (옵션: -a) 해당 도메인에 대한 모든 호스트 정보를 보여준다. (ex: host -a yahoo.co.kr)

netconfig : 부팅시에 적용할 네트워크를 쉽게 설정할 수 있다.

vi /etc/resolv.conf : resolving DNS 주소를 설정 한다.
vi /etc/named.conf : 네임서버의 주소(zone파일)를 설정한다.
vi /etc/sysconfig/network : 네트워크를 사용할수 있도록 설정한다.
vi /etc/sysconfig/network-scripts/ifcfg-eth0 : 랜카드를 설정할 수 있다.(ip, 도메인등)
cat /etc/modules.conf : 랜카드의 인터페이스가 보임.

ifconfig : (옵션: -a) 현재 장착되어있는 랜카드에 대한 IP주소나 MAC주소, 서브넷마스크등의 모든정보를 볼수 있다.

ping : 외부로 패킷을 날린다.

route : 라우팅 테이블을 볼 수 있다.
traceroute : 해당 주소까지 거처가는 라우터의 정보를 보여준다. (ex: traceroute yahoo.co.kr = 야후 홈페이지까지 거처가는 모든 라우터의 정보가 보여짐)

tcpdump : 해당 서버에 주고받는 노드의 정보가 실시간으로 보여짐.

whois : 특정 도메인 정보나 특정 IP주소, 특정 네트워크를 사용하는 기관명을 조회할 수 있다.
(ex: whois -h whois.arin.net tt.co.kr = tt.co.kr이란 도메인에 대해서 최상위 루트 DNS 서버에 질의를 요청한다.)
(ex: whois -h whois.apnic.net tt.co.kr = tt.co.kr이란 도메인에 대해서 ASIA-PACIFIC 지역 DNS 서버에 질의를 요청한다.)
(ex: whois -h whois.ripe.net tt.co.kr = tt.co.kr이란 도메인에 대해서 유럽 지역 DNS 서버에 질의를 요청한다.)
(ex: whois -h whois.krnic.net tt.co.kr = tt.co.kr이란 도메인에 대해서 국내(대한민국) DNS 서버에 질의를 요청한다.)
*jwhois 란 명령은 일일이 해당 도메인 지역 DNS 서버주소를 치지않아도 질의를 할 수 있도록 해준다.

dig : 도메인명으로 정보를 알아볼 수 있다.
(ex: dig yahoo.co.kr = yahoo.co.kr에 대한 네임서버 정보를 볼 수 있다.)
(ex: dig yahoo.co.kr mx = yahoo.co.kr에 대한 메일 네임서버 정보를 볼수 있다.)
(ex: dig yahoo.co.kr +trace = yahoo.co.kr에 대해 root DNS서버 에서부터 질의하는 과정의 정보를 볼 수 있다.)
(ex: dig @ns1.yahoo.com yahoo.co.kr = yahoo의 DNS 네임서버에 대해서 yahoo.co.kr 을 질의 한다.)

-시스템 관련 명령어------------------------------------------------------------------------------------------------
shutdown -h now : 리눅스를 종료한다. 똑같은 명령어로 halt가 있다.
shutdown -r now : 리눅스를 재부팅한다. 똑같은 명령어로 reboot가 있다.

dmesg : 부팅 메세지를 다시 볼수있다.

finger : 현재 접속해있는 계정을 볼수있다.

df : (옵션: -h) 하드디스크의 파티션 사용량을 보여준다.
fdisk : (옵션: -l) 모든 파티션의 정보를 보여준다
*표시되는 형식
hda1 : h= IDE방식의 디스크를 뜻함. s는 SATA나 SCSI방식의 디스크를 뜻함
d= 드라이브 디스크를 뜻함
a= 첫번째 물리적디스크 드라이브를 뜻함. 두번째 물리적디스크 드라이브는 b, 세번째는 c...
1= 첫번째 파티션을 뜻한다. 두번째 파티션은 2, 세번째는 3...

cat /proc/cpuinfo : CPU 정보를 확인 한다.
cat /proc/meminfo : 메모리 정보를 확인 한다.
vmstat : 가상메모리의 상태를 볼 수 있다. (ex: vmstat 1 5 = 1초마다 한번씩 5번 가상메모리 상태를 보여준다.)
free : 시스템의 메모리 상태를 볼 수 있다.

history : 실행했던 명령어를 순차적으로 보여줌.
last : 서버에 접속했던 계정 및 IP, 머물렀던시간 등을 보여준다.

date : 현재 시간을 확인한다.
rdate -s time.bora.net&&clock -w : 서버시간을 동기화 시킨다.

uname : (옵션: -a) 현재 운영체제와 커널 버젼을 확인 할 수 있다.
cat /etc/*rel* : 리눅스 배포판 버젼을 확인 할수 있다.

mkfs : 파일시스템(포맷)을 만든다.

quota : 디스크 사용량을 제한할 수 있다.
edquota : 디스크 사용량을 수정할 수 있다.

-일반 명령어-------------------------------------------------------------------------------------------------------
cd : (옵션: -) 바로 전으로 돌아간다.
(옵션: --) 무조건 루트로 돌아간다.
* cd ~ 은 현재 로그인한 계정의 홈디렉토리로 이동한다.

pwd : 현재 디렉토리를 보여준다.
ls : (옵션: -l) 현재 디렉토리안에 있는 파일들을 자세하게 보여준다.
(옵션: -a) 현재 디렉토리안에 숨겨져있는 파일까지 보여준다.(파일명 앞에 .이 붙는 파일이 숨겨진 파일이다.)
(옵션: -t) 가장 최근에 등록된 파일부터 차례대로 보여줌.
(옵션: -R) 현재 디렉토리 포함 하위 디렉토리 파일까지 보여줌.

du : (옵션: -h) 현재 디렉토리에 대해서 사용 용량을 보여준다.

clear : 현재 보여지는 화면을 깨끗하게 지운다.

; ← 한줄에 여러 파일을 실행할때(ex: cd /home3/오세헌/ ; mkdir aaaaaa = home3/오세헌 디렉토리로 이동한다음 aaaaaa라는 디렉토리를 생성한다.)
|(하이픈) ← 명령어를 실행하면서 나온 결과값에 대해 다른 파일을 실행해 적용할때(ex: find /etc/ |grep aa = etc디렉토리안에 aa라는 글짜가 포함된 파일만 검색해서 보여줌)
(a ; b 와 a | b 의 차이점: a ; b 는 각각의 a와 b가 독립적으로 실행이 되지만 a | b 는 a가 실행되면서 나오는 결과물을 b에 연계되어 실행이 된다.)

head : 파일내용의 윗부분을 볼수 있다.(ex: head -5 오세헌 = 오세헌이라는 파일 내용의 맨 윗줄에서 5줄 까지만 출력한다.)
tail : (옵션: -f) 문서 파일의 내용전체를 한칸씩 읽어내리듯 출력한다.
more : 많은내용의 문서가 출력될때 한페이지당 끈어서 출력되게 한다. 주로 |(하이픈) 을 붙혀서 많이쓴다.
less : more와 비슷한 명령이나 more는 넘어간 페이지를 다시 되돌려 볼수는 없지만 less 명령은 지나쳤던 페이지를 다시 되돌려 볼수있다.

grep : 지정한 단어가 포함된 파일을 출력한다. 주로 |(하이픈) 을 붙혀서 많이쓴다.
(옵션: -v) 지정한 단어가 포함이 되지않은 파일을 출력한다.
find : 디렉토리에서 여러옵션(파일이름,형식,변경한날짜,만들어진시간)으로 파일을 검색해서 출력한다.
(옵션: -mtime) 파일이 생성(수정)된 시간으로 파일을 검색한다.(ex: fine /etc/ -mtime +3 = etc 디렉토리 안에 마지막으로 수정된 날짜로부터 3일이 경과된 파일들을 출력한다.)
locate : 지정한 단어를 파일뿐만아니라 디렉토리까지 검색해서 출력한다.

vi : 문서 편집기.
(글을 쓸 때에는 Insert 키는 누르고 작성, 저장하려면 ESC 키를 누르고 :w, 종료하려면 ESC 키를 누르고 :q, 강제 종료나 강제 저장을 하고 싶다면 각각 명령어 뒤에 !를 붙인다.)

alias : 변수에 단축키를 지정한다. (ex: ll = 'ls -al' → ll 이라는 변수에 ls -al이라는 명령을 넣어준다.)
*일반적으로 alias 명령으로 만든 단축키는 /.bashrc 파일에 등록하여 리눅스가 시작되었을때 자동으로 단축키가 등록되도록 한다.
ln : (옵션 -s) 링크 파일을 만든다.(ex: ln -s /etc//king/osh osh = cd osh를 치면 자동으로 /etc/king/osh 로 이동한다.

cp : 파일을 복사한다.
mv : 파일을 이동시킨다.
touch : 내용없는 파일을 생성한다.
rm : (옵션: -f) 파일을 삭제할때 확인유무를 묻지않고 바로 삭제한다.
(옵션: -r) 하위 디렉토리까지 모두 삭제한다.
mkdir : 디렉토리를 생성한다.
rmdir : 디렉토리를 삭제한다.


'먹고살기 > Unix' 카테고리의 다른 글

공백제거  (5) 2014.03.21
쉘 스크립트  (0) 2011.06.30
리눅스 명령어  (0) 2011.04.29
 

arp

# arp [옵션]

arp는 커널의 ARP 테이블을 조작하기 위한 명령이다. ARP 테이블은 네트워크를 통해 연결되어 있는 호스트의 IP 주소와 실제 물리적인 이더넷 MAC 주소가 대응되어 있는 지도라고 할 수 있다. 실제로 네트워크를 통해 컴퓨터끼리 데이터를 주고받는 데에는 네트워크 카드 제조사에 부여된 하드웨어 주소인 MAC(Media Address Control) 주소를 사용한다. 특정 IP 주소에 대한 네트워크 전송 요청이 생기면 리눅스는 이 ARP 테이블을 보고 물리적인 주소인 MAC 주소를 알아낸다.

-a [IP주소] : ARP 테이블을 표시한다. 명령 뒤에 IP 주소가 지정되면 컴퓨터의 IP 주소와 MAC 주소만 표시된다.

-d [IP주소] : ARP 테이블에서 주소의 호스트를 지운다.

-s : ARP 테이블에 강제로 호스트를 추가하고 호스트의 IP 주소와 MAC 주소를 연결할 때 사용한다.

yum

# yum [명령] [옵션] [패키지이름]

yum은 온라인 패키지 관리 도구이다. yum은 레드햇 패키지 관리 도구인 rpm을 기반으로 한다. 시스템 관리자는 yum을 이용하여 네트워크로 연결되어 있는 패키지 저장소에서 패키지를 검색하거나 내려받아 설치할 수 있다.

check-update : 패키지 저장소의 패키지 정보를 업데이트한다.

search [검색어] : 패키지를 검색한다.

install [패키지이름] : 패키지를 설치한다.

update [패키지이름] : 패키지의 버전을 판올림한다. 특정 패키지 이름을 지정하지 않는다면 시스템에 설치되어 있는 모든 패키지의 버전을 판올림할 것이다.

remove [패키지이름] : 패키지를 없앤다.

smbpasswd

# smbpasswd [옵션]

smbpasswd는 삼바 사용자 계정의 비밀번호를 변경하는 명령이다. 루트 계정에서 smbpasswd 명령을 수행하면 리눅스 서버의 사용자 계정(/etc/passwd에 등록되어 있는 사용자)을 삼바 사용자 계정으로 등록할 수 있다. 이렇게 추가된 삼바 사용자 계정은 /etc/smbpasswd에서 확인할 수 있다.

-r [원격호스트이름] : 비밀번호를 변경할 삼바 서버의 이름을 지정한다.

-a [사용자이름] : 삼바 사용자 계정을 추가한다.

-d [사용자이름] : 삼바 사용자 계정을 비활성화(disabled)한다.

-e [사용자이름] : 삼바 사용자 계정을 활성화(enabled)한다.

-n : 사용자 계정의 비밀번호가 없도록 설정한다.

usermod

# usermod [옵션] [사용자계정]

usermod는 리눅스 사용자 계정의 정보를 변경하기 위한 명령이다.

-c [사용자에대한설명] : 사용자에 대한 설명 필드의 내용을 수정한다.

-d [홈디렉터리] : 사용자의 홈 디렉터리를 변경한다.

-e [계정만료일] : 사용자의 비밀번호 만료 날짜를 변경한다.

-G [그룹] : 사용자의 그룹을 변경한다.

-u [UID] : 사용자의 UID(User ID)를 변경한다.

-l [사용자계정] : 사용자의 계정 이름을 변경한다.

smbclient

# smbclient //[서버이름]/[공유자원이름] [비밀번호] [옵션]

smbclient는 SMB 프로토콜을 통해 네트워크 공유 자원에 접근할 수 있는 클라이언트 프로그램이다. ftp 클라이언트와 같이 명령 행을 바탕으로 한 서버와의 상호작용을 제공한다. '//[서버이름]/[공유자원이름]'과 같은 형식으로 네트워클 공유 자원에 접근할 수 있으며 자원에 비밀번호가 설정되어 있는 경우 직접 명령 행에서 비밀번호를 입력할 수 있다. smbclient로 로그인에 성공하면 smbclient 프롬프트('smb:\=')가 나타나며 ftp 클라이언트와 비슷한 여러 가지 명령을 사용할 수 있다.

-l [IP주소] : 접속 대상 호스트의 IP 주소를 입력한다.

-p [포트번호] : 클라이언트가 요청을 받아들일 포트 번호를 입력한다.

-L [서버이름] : 컴퓨터가 제공하는 공유 자원과 서비스에 대한 목록을 표시한다.

-t [터미널코드] : 한글 파일 이름을 보기 위한 문자 세트를 지정할 수 있다.

-s [환경설정파일] : 삼바 환경설정 파일의 위치를 지정한다.

-l [로그파일] : 지정된 파일로 로그 기록을 내보낸다.

-W [작업그룹이름] : 클라이언트가 연결을 원하는 작업그룹을 지정한다.

wget

# wget [옵션] [주소]

wget는 텍스트 환경에서 인터넷을 통해 파일을 받아오기 위한 명령이다. 인터넷의 기본 프로토콜인 HTTP, FTP 프로토콜을 지원한다. 단순히 파일의 주소만 입력해주기만 하면 파일을 내려받기 시작한다.

-b : 내려받는 파일의 용량이 많을 때 wget 명령을 백그라운드 프로세스로 실행한다.

-o [파일이름] : 파일을 받아오는 동안의 로그 정보를 남길 파일을 지정한다.

-i [파일이름] : 받아올 파일이 많을 경우 파일의 목록을 하나의 파일로 만들어서 wget 명령에 전달할 수 있다. 받아올 파일의 목록이 기록되어 있는 파일을 지정한다.

sort

# sort [옵션]

sort는 텍스트 파일의 문자를 줄 단위로 정렬하는 명령이다. 명령 뒤에 [파일이름]이 없다면 정렬 결과를 표준 출력(모니터)으로 출력할 것이다.

-c : 이미 정렬된 상태인지 검사하고 정렬된 상태라면 정렬하지 않는다.

-b : 정렬을 할 때 행의 앞부분에 있는 공백을 무시한다.

-d : 정렬의 기준으로 영어 알파벳 대소문자와 숫자만을 고려한다.

-o [파일이름] : 정렬 결과를 지정된 파일로 출력한다.

-r : 내림차순으로 정렬한다.

ssh

# ssh [사용자]@[SSH서버주소]

# ssh -l [사용자] [SSH서버주소]

ssh는 명령 행에서 사용할 수 있는 OpenSSH 클라이언트 프로그램이다. 리눅스의 명령 프롬프트에서 원격 접속을 위해 사용된다.

-l [사용자계정] : 서버에 로그인할 사용자 계정을 지정한다.

-p [포트번호] : SSH 서버의 포트 번호를 지정한다.

-F [환경설정파일] : ssh 클라이언트의 기본 환경설정 파일을 지정된 설정 파일로 대체한다.

logout

# logout

logout은 현재의 세션을 끝내기 위한 명령이다. X 윈도우 세션에서 로그아웃을 하면 X 윈도우 사용자의 세션을 끝내고 처음 로그인 화면으로 돌아가는 것과 같은 원리로 원격 터미널에서 로그아웃하면 터미널 접속을 끝낸다.

ssh-keygen

# ssh-keygen [옵션]

ssh-keygen은 리눅스에서 SSH 접속에 사용되는 인증 키를 만드는 명령이다. 명령을 입력하고 키가 저장될 파일을 지정한 다음 키에 접근하기 위해 필요한 passphrase를 지정하면 SSH 인증 키가 만들어진다.

-t [rsa 또는 rsa1] : 인증 키 형식을 지정한다. rsa는 SSH 프로토콜 버전 2로, rsa1은 SSH 프로토콜 버전 1로 저장한다.

-f [파일이름] : 인증 키를 저장할 파일을 지정한다.

init

# init [옵션(실행단계)]

init 명령은 시스템 초기화 프로세스 init를 시작(재시작)하는 명령이다. 이때 init 명령의 옵션으로 실행 단계를 지정하면 현재 세션을 끝내고 inittab에 설정되어 있는 각 실행 단계로 전환합니다. 예를 들면 잠깐 동안 X 윈도우 환경에서 콘솔 환경으로 전환할 때 유용하게 사용할 수 있다. /etc/inittab을 편집하여 기본 실행 단계를 3으로 지정하고 시스템을 재부팅할 필요 없이 터미널에서 'init 3'이라는 명령을 입력하면, X 윈도우를 끝내고 바로 콘솔 환경으로 전환될 것이다.

init 0 : 시스템을 끝낸다.

init 1 ~ init 5 : 지정한 실행 단계로 부팅한다.

init 6 : 시스템을 다시 재부팅한다.

init S 또는 init single : 단일 사용자 모드로 부팅한다.

telnet

# telnet [옵션] [접속대상호스트] [포트번호]

telnet 명령은 원격 접속을 위한 TELNET 프로토콜을 통해서 다른 호스트에 접속하기 위한 명령이다. telnet 클라이언트 명령으로서 접속 대상 호스트에 telnet 서버가 운영되고 있어야 접속할 수 있다. 호스트 다음에 특정 포트 번호(텔넷의 기본 포트 번호는 23번으로 예약되어 있음)를 입력함으로써 다른 포트 번호를 사용하는 호스트에 접속할 수 있다.

-a : 자동 접속을 시도한다. 환경 변수 USER에 설정되어 있는 현재 로그인해 있는 사용자 계정을 접속 대상 호스트로 전송할 것이다.

-l : 접속 대상 호스트에 로그인할 사용자 계정을 지정한다.

grub-install

# grub-install [옵션] [장치이름]

grub-install은 부트로더 GRUB를 지정한 영역에 설치하는 명령이다. 장치 이름에는 디스크 파티셔느이 장치 파일 이름을 입력한다. 이때 일반적인 리눅스 시스템 장치 파일 이름인 /dev/hdXX와 같은 형식으로 입력할 수도 있지만, GRUB 형식의 이름 hd0과 같이 사용하는 것도 허용된다.

--root-directory=[디렉터리] : 루트 디렉터리 대신 GRUB 이미지를 설치할 디렉터리를 명시할 수 있다.

--force-lba : 오래되거나 버그와 같은 문제가 있는 바이오스 환경에서 GRUB를 설치하기 위해 LBA 모드를 활성화한다.

mke2fs

# mke2fs [옵션] [장치이름]

mke2fs는 디스크 장치에 리눅스 파일 시스템을 만들기 위한 명령이다. 장치 이름에는 /dev/hdXX와 같이 디스크 파티션의 장치 파일 이름을 입력한다.

-b [블록크기] : 바이트 단위로 만들어지는 파일 시스템의 블록 크기를 지정한다.

-c : 파일 시스템을 만들면서 배드 블록이 있는지 물리적으로 점검한다.

-v : 파일 시스테이 만들어지는 과정을 자세하게 표시한다.

startx

# startx [클라이언트] [옵션] [--서버] [옵션]

startx는 X 윈도우를 실행하는 명령 스크립트이다. '스크립트'라는 말에서 알 수 있듯이 단순히 X 윈도우를 실행하는 명령뿐만 아니라 X 윈도우를 실행하기 위해 등록되어 있는 다양한 환경설정 명령을 먼저 내리고 최종적으로 X 윈도우를 실행한다.

-- -depth [색상] : X 서버의 색상수를 지정한다.

-- -dpi [해상도] : X 서버의 해상도를 지정한다.

export

# export [환경변수]=[값]

export 명령은 환경 변수를 지정, 변경하거나 현재 정의되어 있는 환경 변수를 보여주는 명령이다. 환경 변수를 변경함으로써 명령 프롬프트에서 실행한 프로그램에 영향을 미치게 된다. 다만 export 명령에 의해 변경되 환경 변수는 export 명령을 실행한 사용자의 로그아웃 전까지만 유효하며 영구적으로 변경하기 위해서는 환경 변수를 정의하는 설정 파일(/etc/profile 등)을 직접 수정해야 한다.

uname

# uname [옵션]

uname 명령은 현재 시스템에 대한 정보를 표시하는 명령이다. 다양한 옵션을 이용해서 원하는 정보를 확인할 수 있다.

-a : 시스템의 모든 정보를 표시한다. -s : 시스템의 커널의 이름을 표시한다.

-n : 시스템의 호스트 이름을 표시한다. -r : 커널의 릴리스 정보를 표시한다.

-v : 시스템의 커널 버전을 표시한다. -m : 하드웨어의 아키텍처 정보를 표시한다.

-i : 하드웨어 플랫폼 정보를 표시한다.

init

init는 실행 단계를 변경할 수 있는 명령이다.

setkeycodes

# setkeycodes [스캔코드] [키코드]

setkeycodes 명령은 스캔 코드를 키코드에 대응시키는 명령이다. 명령의 첫 번째 인자는 스캔 코드로서 키마다 정해져 있는 키 값을 뜻한다. 키코드는 커널에서 키보드의 각 키마다 부여한 키 값으로 setkeycodes는 스캔 코드 값을 두 번째 인자인 키 코드 값으로 커널에 등록할 것이다.

showkey

# showkey [옵션]

showkey는 키보드로부터 입력된 키를 테스트하기 위한 명령이다. 키보드 키를 누르는 순간 해당 키 코드에 대한 press 메시지가 출력되고 키에서 손을 떼는 순간 release 메시지가 출력될 것이다.

-s : 키보드의 스캔 코드 값을 출력한다.

-k : 키보드의 키 코드 값을 출력한다.

-a : 키보드의 아스키 값을 출력한다.

xev

# xev [옵션]

xev는 X 윈도우에서 벌어지는 이벤트를 출력하는 명령이다. xev 명령을 실행하면 창이 하나 뜨는데 이 창에서 벌어지는 키보드 입력, 마우스의 이동, 마우스 클릭 등 모든 이벤트를 수치 정보로 보여준다.

-display : 이벤트 정보를 출력할 X 윈도우 서버를 지정한다.

-geometry : 이벤트 정보를 받아들일 창의 크기, 위치를 지정한다.

-bw : 이벤트 정보를 받아들일 창 테두리선의 두께를 지정한다.

xmodmap

# xmodmap [옵션] [파일이름]

xmodmap은 X 윈도우에서 키보드의 키 코드를 해당하는 키와 대응시키는 명령이다. 현재 키보드에 설정되어 있는 키코드 값을 변경하거나 새로운 키코드 값을 추가한다. 옵션 keycode를 이용해서 하나의 키에 대한 키코드를 지정할 수도 있지만, 예제에 나온 것처럼 Xmodmap이라는 파일로 여러 키의 키코드를 일괄적으로 등록하는 것이 일반적이다.

-e : 특정 키 코드를 해당 키와 대응시킨다.

-pk : 현재 키 코드에 대응되어 있는 키 값을 보여준다.

locale

# locale [옵션]

locale은 현재 로케일 상태를 확인하는 명령이다. locale 명령으로 확인할 수 있는 환경 변수는 LANG(언어), LC_CTYPE(문자), LC_COLLATE(문자 정렬 순서), LC_MESSAGE(메시지 표현을 위한 특별한 설정), LC_NUMERIC(숫자), LC_MONETARY(화폐 단위), LC_TIME(시간과 날짜) 등이 있다.

-a : 로케일을 확인한다.

dmesg

# dmesg [옵션]

dmesg는 커널의 상태 정보를 확인하기 위한 명령이다. 리눅스가 부팅될 때의 각종 메시지를 다시 볼 때 이 명령을 사용한다.

-n [실행단계] : 해당 실행 단계의 상태 정보만 보여준다.

lsmod

# lsmod

lsmod는 커널 메모리에 올라가 있는 모듈들의 목록을 보여주는 명령이다. 모듈의 이름(Module), 모듈의 크기(Size), 모듈이 사용되고 있는 횟수(Used), 해당 모듈을 참조하고 있는 다른 모듈(by)를 표시한다. 이 명령의 결과는 /proc/modules에서도 확인할 수 있다.

modprobe

# modprobe [모듈이름] [옵션]

modprobe 명령은 커널 모듈을 커널 메모리에 적재하는 데 사용하는 명령이다. 모듈 이름에는 커널에 올리려는 모듈을 /lib/modules 디렉터리에서 찾고 이를 입력한다.

rmmod

# rmmod [옵션] [모듈이름]

rmmod는 커널 메모리에서 해당 모듈을 내릴 때 사용하는 명령이다. 어떤 장치의 경우 모듈을 함부로 내릴 수 없는데, rmmod 명령을 입력하면 Device or resource busy라는 메시지가 나타날 것이다.

-r : 의존 관계에 있는 모든 모듈을 한꺼번에 내린다.

mysqladmin

# mysqladmin [옵션] [명령]

mysqladmin은 MySQL 데이터베이스 관리자 명령이다. 명령에 특정 키워드를 입력하면 데이터베이스에 직접 로그인하지 않은 리눅스 명령 프롬프트에서 데이터베이스 관리와 관련된 작업(MySQL 종료, 재시작, 새로운 데이터베이스 생성과 삭제 등)을 수행할 수 있다.

다음과 같은 명령을 사용할 수 있다.

status : 데이터베이스의 상태를 출력한다.

shutdown : 데이터베이스를 끝낸다.

reload : 데이터베이스를 재시작한다.

create [데이터베이스이름] : 새로운 데이터베이스를 만든다.

drop [데이터베이스이름] : 데이터베이스를 지운다.

-u [사용자 계정] : 데이터베이스에 접속하는 MySQL 사용자 계정을 지정한다.

-p [비밀번호] : 데이터베이스에 접속하기 위한 사용자 계정의 비밀번호를 지정한다(※ 주의 : -p 옵션 뒤에 공백 없이 비밀번호를 입력해야 한다).

--default-character-set=[문자세트] : 데이터베이스의 기본 문자 세트를 지정한다.

-h [호스트이름] : 접속할 대상 데이터베이스의 호스트 이름을 지정한다.

-P [포트번호] : 접속할 대상 데이터베이스의 포트 번호를 지정한다.

--protocol=[프로토콜] : 데이터베이스에 접속할 때 사용할 프로토콜을 지정한다.

mysql

# mysql [옵션] [데이터베이스이름]

mysql은 MySQL의 데이터베이스에 접속하기 위한 클라이언트 명령 행 도구이다. 로그인에 성공하면 MySQL 명령 프롬프트('mysql>')가 나타나는데 여기에서 데이터베이스를 조작할 수 있는 명령을 내릴 수 있다.

-D [데이터베이스이름] : 접속할 데이터베이스 이름을 지정한다.

-u [사용자계정] : 데이터베이스에 접속하는 MySQL 사용자 계정을 지정한다.

-p [비밀번호] : 데이터베이스에 접속하기 위한 사용자 계정의 비밀번호를 지정한다(※ 주의 : -p 옵션 뒤에 공백 없이 비밀번호를 입력해야 한다).

--default-character-set=[문자세트] : 데이터베이스의 기본 문자 세트를 지정한다.

-h [호스트이름] : 접속할 대상 데이터베이스의 호스트 이름을 지정한다.

-P [포트번호] : 접속할 대상 데이터베이스의 포트 번호를 지정한다.

--protocol=[프로토콜] : 데이터베이스에 접속할 때 사용할 프로토콜을 지정한다.

sh

# sh [셸스크립트 파일]

sh는 리눅스와 유닉스의 기본 셸 스크립트 언어로 짜인 스크립트 파일을 실행하는 명령이다.

ping

# ping [옵션]

ping은 네트워크 연결 상태를 검사하기 위한 도구이다. ICMP 프로토콜 형식의 패킷을 보내어 연결 상태를 확인한다.

-c [횟수] : ping을 통해 보낼 패킷의 수를 지정한다.

-i [초] : 정해진 시간 간격(초 단위)으로 패킷을 보낸다.

-l [네트워크 인터페이스] : 패킷을 보낼 네트워크 인터페이스를 지정한다.

-s [패킷크기] : 보낼 패킷의 크기(바이트 단위)를 지정한다.

-t [ttl] : 패킷의 ttl 값을 지정해서 보낸다.

※ttl(Time To Live) 값이란?

-> ttl은 ping으로 보낸 패킷이 네트워크에서 영원히 돌아다니는 것을 막기 위해(이렇게 되면 네트워크의 부하가 커질 것이다) 패킷이 자동으로 소멸하는 시간 간격을 말한다. ttl의 시간 간격은 일반적으로 라우터를 통과할 때마다, 패킷이 다른 네트워크로 넘어갈 때마다 줄어들어 ttl이 0이 되면 패킷은 소멸한다.

sestatus

# sestatus [옵션]

sestatus는 SELinux 시스템의 상태를 확인하기 위한 명령이다.

-v : /etc/sestatus.conf에 등록되어 있는 파일, 프로세스 보안 문맥을 확인한다.

chcon

# chcon [옵션] [보안문맥] [파일이름]

chcon은 파일의 보안 문맥을 변경할 때 사용하는 명령이다.

-r : 파일 보안 문맥 중 역할(role) 필드를 변경한다.

-t : 파일 보안 문맥 중 유형(type) 필드를 변경한다.

-u : 파일 보안 문맥 중 신분(identity) 필드를 변경한다.

-R : 하위 디렉터리의 파일과 디렉터리에 대해 보안 문맥을 적용한다.

setsebool

# setsebool [보안정책] [1 또는 0]

setsebool은 system-config-securitylevel에서 설정할 수 있는 SELinux의 보안 정책을 터미널 환경에서 제어하는 명령이다. 보안 정책은 각 항목별로 표시되는데 1은 활성, 0은 비활성 상태임을 나타낸다.

-P : -P 옵션이 주어지면 보안 정책을 디스크에 반영하게 된다. 다시 부팅을 하더라도 설정한 보안 정책이 유지될 것이다. -P 옵션이 없다면 현재 설정되어 있는 보안 정책에만 영향을 미칠 것이며, 시스템의 보안 정책이 정의되어 있는 파일 /etc/selinux/SELINUXTYPE/booleans은 수정되지 않을 것이다.

crontab

# crontab [-u 사용자] [파일] 옵션

crontab 명령은 작업할 내용을 작성하거나 현재 설정되어 있는 작업 스케줄을 확인하거나 이미 설정되어 있는 작업을 지우는 등의 스케줄 관리를 할 수 있다.

-u : 작업을 수행할 사용자를 지정한다.

-e : 작업할 내용을 작성한다.

-l : 현재 설정되어 있는 작업 내용을 확인한다.

-r : 설정되어 있는 작업 스케줄 정보를 지운다.

rdate

# rdate [옵션] [타임서버주소]

rdate는 네트워크를 통해 타임 서버에서 날짜와 시간 정보를 받아오는 명령이다.

-p : 타임 서버에서 받은 날짜와 시간 정보를 표시한다.

-s : 타임 서버에서 받은 날짜와 시간 정보를 시스템의 현재 시간으로 지정한다.

-u : 타임 서버에서 날짜와 시간정보를 받는 데 UDP 프로토콜을 사용한다.

hwclock

# hwclock [옵션]

hwclock는 하드웨어 시간(바이오스에서 받아온 시간 정보)을 현재 시스템의 시간으로 설정하는 명령이다.

-r : 받아온 하드웨어 시간을 표시한다.

-w 또는 --systohc : 받아온 하드웨어 시간을 시스템의 현재 시간으로 지정한다.

--utc : 시간 정보를 국제적인 시간 기준인 UTC(Universal Time Coordinated)로 지정한다.

--localtime : 시간 정보를 일반적인 지역별 시간대로 지정한다.

logrotate

# logrotate

logrotate는 시스템 로그를 순환시키기 위한 명령이다.

-d : logrotate를 디버그 모드로 실행한다.

-f : 로그 순환을 중지한다.

-s [상태파일] : 특정 상태 파일에 대한 순환을 지시한다. 다양한 형태의 로그를 순환시킬 때 필요한 옵션이다.


'먹고살기 > Unix' 카테고리의 다른 글

공백제거  (5) 2014.03.21
쉘 스크립트  (0) 2011.06.30
리눅스 실무 명령어  (0) 2011.04.29
SQL _ HAVING 먹고살기/Oracle 2011. 4. 29. 16:34

1.데이터의 빠진 부분 찾기

SeqTbl

seq

name

1

마이크

2

제인

3

데이브

5

조안

6

메리

8

위와 같은 일련번호를 가진 테이블이 있다고 하자. 그런데 일련번호가 있다고 해도, 번호가 연속적이지 못하다. 4와 7이 빠져있다. 이 테이블에서 데이터가 빠져있는지를 확인해 보는 SQL을 만들어보자. 만약 이 테이블이 파일이고 절차적언어를 이용한다면 다음과 같은 순서로 해결할 것이다.

1.일련번호를 정렬시킨다.

2.루프해서 한행씩 다음행과 번호를 비교한다.

이런 간단한 순서 안에서도 절차적언어와 파일 시스템의 특징을 알 수 있다. 파일의 레코드는 순서를 가지고 있고, 언어는 이를 정렬시킨다는 것이다. 하지만 테이블의 행은 순서를 가지고 있지 않고 SQL도 정렬 연산자를 가지고 있지 않다는 것이다.(ORDER BY는 SQL의 연산자가 아니다)대신 SQL은 복수행을 하나의 집합으로 취급한다. 테이블 전체를 하나의 집합으로 본다면 다음과 같은 SQL문을 만들 수 있을 것이다.

SELECT'결함있음'ASgap
FROMSeqTbl HAVINGCOUNT(*) <> MAX(seq);

gap ------------- '결함있음' 

COUNT(*)의 행수와 번호의 최대값이 같다면 처음부터 끝까지 빠짐없이 카운트되었다는 의미이다.

그런데 이 SQL문에는 GROUP BY구가 없다. 이런 경우, 테이블 전체가 한행으로 집약되어진다. 이럴 때도 HAVING구는 문제없이 사용가능하다. 현재의 표준 SQL에서는 HAVING구를 단독으로 쓸 수 있다. 단, SELECT구에 원테이블의 열을 참조할 수 없기 때문에 위의 문제처럼 정수를 지정하든지, 「SELECT COUNT(*)」처럼 집약함수를 쓸 필요가 있다.

2. HAVING구로 서브쿼리:최빈치를 구하기

아래와 같은 연봉을 나타내는 졸업생 테이블이 있다. 이 학교의 평균연봉을 계산하면 55000달러이지만 이는 샘슨의 연봉이 다른 졸업생에 비해 10배나 높기 때문이다. 단순평균은 이런 값(샘슨의 연봉같은)에 영향을 많이 받는 단점이 있는데 이런 경우, 집단의 경향을 가장 정확하게 나타내는 지표 중에 하나인 최빈치를 이용해서 문제를 해결해보자.

name income
샘슨 400000
마이클 30000
화이트 20000
아놀드 20000
스미스 20000
로렌스 15000
허드슨 15000
켄트 10000
베카 10000
스코트 10000

수입이 같은 졸업생을 하나로 하는 집단을 만들어 그 집단들로부터 요소의 수가 가장 많은 집함을 찾으면 된다. 아래와 같은 SQL문을 만들 수 있을 것이다.

SELECT income, COUNT(income) cnt
FROM graduates
GROUP BY income
HAVING COUNT(*) >= ALL(SELECT COUNT(*)
FROM graduates
GROUP BY by income)

INCOME CNT
--------- ----------
10000 3
20000 3

ALL 대신 Null과 공집합일 경우에 신경을 쓴다면 MAX,MIN도 사용가능하다. 지금은 "가장 많은" 경우이므로 MAX함수를 사용한다.

SELECT income
FROM Graduates
GROUP BY income
HAVING COUNT(*) >= ( SELECTMAX(cnt)
FROM ( SELECT COUNT(*) AS cnt
FROM Graduates
GROUP BY income) TMP) ;

3.Null을 포함하지 않는 집합을 찾기

COUNT함수의 사용법에는 COUNT(*)과 COUNT(열명)의 2가지 방법이 있다. 이 둘의 차이가 2가지 있다. 첫번째는 퍼포먼스의 차이이고 두번째는 COUNT(*)는 Null을 세지만 COUNT(열명)은 Null을 제외한다는 점이다.

Students

student_id

dpt

sbmt_date

100

이학부

2005-10-10

101

이학부

2005-09-22

102

문학부

 

103

문학부

2005-09-10

200

문학부

2005-09-22

201

공학부

 

202

경제학부

2005-09-25

학생이 레포트를 제출하면, 제출일에 날짜를 기입한다. 미제출일 때는 Null이다. 이 테이블에서 소속된 전학생이 제출완료된 학부를 찾아보자.

--COUNT함수 이용--

SELECT dpt
FROM Students
GROUP BY dpt
HAVING COUNT(*) = COUNT(sbmt_date);

--CASE식 이용--

SELECT dpt
FROM Students
GROUP BY dpt
HAVING COUNT(*) = SUM(CASE WHEN sbmt_date IS NOT NULL
THEN 1
ELSE 0 END);

이번에는 "전원이 9월중에 제출 완료된 학부"를 선택하는 SQL문을 만들어보자.

SELECT dpt
FROM students
GROUP BY dpt
HAVING COUNT(*) = SUM(CASE WHEN sbmt_date is not null

AND TO_DATE(sbmt_date) BETWEEN '20050901' AND '20050930'
THEN 1

ELSE 0 END);

4. 모든조건을 만족하는 가게 찾기

Items ShopItems

item shop item
맥주 대구 맥주
종이기저귀 대구 종이기저귀
자전거 대구 자전거
대구 커텐
서울 맥주
서울 종이기저귀
서울 자전거
부산 테레비
부산 종이기저귀
부산 자전거



「item」테이블의 모든 상품을 갖추고 있는 가게를 선택해보자.

SELECT DISTINCTshop
FROM ShopItems
WHEREitem IN(SELECT item FROM Items);

shop
--------
대구
서울
부산

「ShopItems」테이블처럼 한개의 실체(여기서는 가게)에 대한 정보가 복수행에 분산되어져 있는 경우에는 WHERE구에서 단순히 OR 나 IN으로 조건을 지정해도 정답이 얻기가 힘들다. WHERE구에 지정된 조건은 어디까지나 1행에 대해서 적용되기 때문이다.

여기서 IN의 조건은 결국 「Items」테이블의 상품중 어느 한가지라도 있으면 결과에 포함되어져 버리게 된다. 그렇다면 복수행에 걸쳐 있는 조건, 즉 집합에 대한 조건.을 설정하려면 어떻게 해야 될까? 바로 HAVING구를 이용하면 된다.

SELECT SI.shop
FROM ShopItems SI, Items I
WHERE SI.item = I.item
GROUP BY SI.shop
HAVING COUNT(SI.item) = (SELECT COUNT(item) FROM Items);

shop
--------
대구
서울

기대하던 결과가 나왔다.

그런데 여기서 주의할 점이 있다!

SELECT SI.shop
FROM ShopItems SI, Items I
WHERE SI.item = I.item
GROUP BY SI.shop
HAVING COUNT(SI.item)
= COUNT(I.item);

shop
--------
대구
서울
부산

보다시피 이 조건으로는 결과로 모든 가게가 선택되어졌다. 이것은 결합의 영향을 받아서 COUNT(I.item)의 값이 원래의 「Items」테이블의 행수가 아니게 되어버렸기 때문이다.그 결과를 보자.

SELECT SI.shop, COUNT(SI.item), COUNT(I.item)
FROM ShopItems SI, Items I
WHERE SI.item = I.item
GROUP BY SI.shop;

SHOP COUNT(SI.ITEM) COUNT(I.ITEM)
---------------- -------------- -------------
대구 3 3
부산 2 2
서울 3 3

자, 이번에는 상품마스터에 없는 커텐을 갖고 있는 대구점을 제외한 서울점만 선택하는 SQL문을 만들어보자.

SELECT SI.shop
FROM ShopItems SI, Items II
WHERE SI.item=I.item(+)
GROUP BY SI.shop
HAVING COUNT(SI.item) = (SELECT COUNT(item) FROM Items) /* 조건1 */
AND COUNT(I.item) = (SELECT COUNT(item) FROM Items); /* 조건2 */

shop
--------
서울

「ShopItems」테이블을 마스터로 해서 외부결합을 하면 「item」테이블에 존재하지 않는 커텐과 테레비는 NULL로써 I.item열에 나타난다.

조건1에 의해서 COUNT(SI.item)=4인 대구점이 제외 되고, COUNT(I.item)=2인 부산점이 제외된다.

shop SI.item I.item
대구 맥주 맥주
대구 종이기저귀 종이기저귀
대구 자전거 자전거
대구 커텐   -NULL
서울 맥주 맥주
서울 종이기저귀 종이기저귀
서울 자전거 자전거
부산 테레비   -NULL
부산 종이기저귀 종이기저귀
부산 자전거 자전거

[출처] SQL _ HAVING|작성자 미우


'먹고살기 > Oracle' 카테고리의 다른 글

[Oracle] distinct, rowid 중복 제거, 최신 데이터 하나만 가져오기  (1) 2011.06.30
Sysdate  (0) 2011.06.02
SQL _ 상관서브쿼리  (0) 2011.04.29
SQL _ HAVING_2  (0) 2011.04.29
SQL _ CASE식  (0) 2011.04.29

상관서브쿼리를 이용해서 행과 행을 비교하기

SQL에서는 같은 행내의 열끼리 비교하는 것은 간단하다. 단순히 WHERE구에 「col_1 = col_2」처럼 쓰면 되기 때문이다. 하지만 다른 행의 열끼리를 비교하는 것은 그리 간단한 일이 아니다. SQL에서 행간 비교시 위력을 발휘하는 것인 상관서브쿼리, 특히 자기결합과 함께 쓰일 때이다.

여기서 잠깐! 상관서브쿼리란..? 내부의 쿼리에서 외부 쿼리의 테이블의 데이터를 참조하는 쿼리. 이때 메인 쿼리의 테이블의 행마다 서브쿼리가 반복 실행되어진다.

사용예_1 : 납품일이 2001년 4월 1일인 상품을 상관서브쿼리를 이용해서 참조

--상관서브쿼리--


SELECT * FROM 상품테이블 AA
WHERE '20010401' IN (SELECT 납품일
FROM 주문테이블 BB
WHERE AA.상품코드 = BB.상품코드);
--결과--
상품코드 상품명 단가

───── ─── ──
101 BEER 500
102 JUICE 400

사용예_2 :주문개수를 납품일별로 집계해서, 각자의 합계가 주문개수의 최대치를 150넘길 때만 참조

--HAVING구에서 상관서브쿼리이용--

SELECT SUM(주문개수),납품일
FROM 주문테이블 PP
GROUP BY 납품일

HAVING SUM(주문개수) > (SELECT 150 + MAX(주문개수)
FROM 주문테이블 QQ
WHERE PP.납품일 = QQ.납품일);

--결과--
SUM(주문개수) 납품일
─────── ────
650 20010401
485 20010402
490 20010403

Sales

year

sale

1990

50

1991

51

1992

52

1993

52

1994

50

1995

50

1996

49

1997

55

위의 테이블을 이용해서 작년과 비교해서 「년간판매실적이 늘었는지 줄었는지 그대로인지」를 SQL문으로 만들어보자. 먼저 「그대로였다」를 SQL문으로 작성해보자.

--상관서브쿼리이용--

SELECT year,sale
FROM Sales S1
WHERE sale = (SELECT sale
FROM Sales S2
WHERE S2.year = S1.year - 1)
ORDER BY year;

「Sales」테이블과 별도로 「작년의 행」을 보유하고 있는 집합 S2를 추가한다.서브쿼리내의 「S2.year = S1.year -1」이라는 조건에 의해서 비교대상의 행을 1행 밀어내는 것이다.

--셀프조인이용--
SELECT S1.year, S1.sale
FROM Sales S1, Sales S2
WHERE S2.sale = S1.sale
AND S2.year = S1.year - 1
ORDER BY year;

--결과--

YEAR SALE
----- ----------
1993 52
1995 50

이번에는 년도별 판매실적 비교결과를 한눈에 나타내는 SQL문을 만들어보자.

--상관쿼리이용--

SELECT S1.year, S1.sale,
CASE WHEN sale =
(SELECT sale
FROM Sales S2
WHERE S2.year = S1.year - 1) THEN '→'

WHEN sale >
(SELECT sale
FROM Sales S2
WHERE S2.year = S1.year - 1) THEN '↑'
WHEN sale
(SELECT sale
FROM Sales S2
WHERE S2.year = S1.year - 1) THEN '↓'
ELSE '-' END AS var
FROM Sales S1
ORDER BY year;


--결과--
YEAR SALE VA
------ ---------- --
1990 50 ―
1991 51 ↑
1992 52 ↑
1993 52 →
1994 50 ↓
1995 50 →
1996 49 ↓
1997 55 ↑

--셀프조인이용--

SELECT S1.year, S1.sale,

CASE WHEN S1.year = S2.year THEN '→'

WHEN S1.year > S2.year THEN '↑'

WHEN S1.year < S2.year THEN '↓'

FROM Sales S1, Sales S2

WHERE S2.year = S1.year -1
ORDER BY S1.year;

--결과--
YEAR SALE VA
------- ---------- --
1991 51 ↑
1992 52 ↑
1993 52 →
1994 50 ↓
1995 50 →
1996 49 ↓
1997 55 ↑

Sales2

year

sale

1990

50

1992

50

1993

52

1994

55

1997

55

과거의 데이터가 빠져있는 년도가 있는 테이블이 있다. 이런 경우 앞의 Sale1과 같이 「올해 -1」과 같은 조건설정이 불가능하다. 가장 일반적으로 가장가까운 행을 비교대상으로 할 필요가 있다. 어느년도에서 봐도 「과거에 가장 가까운 년도」라는 것은 다음 두가지 조건을 만족하는 년도를 말하는 것이다.

1. 자신보다 앞의 년도에 있을 것.

2. 조건 1을 만족하는 년도 중에서 최대값일 것

이 조건을 SQL문으로 바꾸면 다음과 같다.

--상관서브쿼리--

SELECT year, sale
FROM Sales2 S1
WHERE sale =
(SELECT sale
FROM Sales2 S2
WHERE S2.year =
(SELECT MAX(year) /* 조건2:조건1을 만족하는 년도 중에서 최대*/
FROM Sales2 S3
WHERE S1.year > S3.year)) /* 조건1:자신보다 과거*/
ORDER BY year;

--셀프조인--

SELECT S2.year AS pre_year, S1.year AS now_year
FROM Sales2 S1, Sales2 S2
WHERE S1.sale = S2.sale
AND S2.year = (SELECT MAX(year)
FROM Sales2 S3
WHERE S1.year > S3.year)
ORDER BY now_year;

--결과--
YEAR SALE
----- ----------
1992 50
1997 55

현재의 값과 가장 가까운값의 차분을 구하는 것도 가능하다.

--상관서브쿼리 : 시작시점이 결과에 포함되지 않음--
SELECT S2.year AS pre_year,
S1.year AS now_year,
S2.sale AS pre_sale,
S1.sale AS now_sale,
S1.sale - S2.sale AS diff
FROM Sales2 S1, Sales2 S2
WHERE S2.year = (SELECT MAX(year)
FROM Sales2 S3
WHERE S1.year > S3.year)
ORDER BY now_year;

-- 자기외부결합이용 : 시작시점도 결과에 포함됨--
SELECT S2.year AS pre_year,
S1.year AS now_year,
S2.sale AS pre_sale,
S1.sale AS now_sale,
S1.sale - S2.sale AS diff
FROM Sales2 S1LEFT OUTER JOIN Sales2 S2
ON S2.year = (SELECT MAX(year)
FROM Sales2 S3
WHERE S1.year > S3.year)
ORDER BY now_year;

은행계좌의 입출금을 기록한 테이블에서 누적을 구해보자

Accounts

pro_date
(
처리일)

prc_amt
(
처리금액)

2006-10-26

12,000

2006-10-28

2,500

2006-10-31

-15,000

2006-11-03

34,000

2006-11-04

-5,000

2006-11-06

7,200

2006-11-11

11,000

---OLAP함수이용--

SELECT prc_date, prc_amt,
SUM(prc_amt) OVER (ORDER BY prc_date) AS onhand_amt
FROM Accounts;

--결과--

PRC_DATE PRC_AMT ONHAND_AMT
-------- ---------- ----------
06-10-26 12000 12000
06-10-28 2500 14500
06-10-31 -15000 -500
06-11-03 34000 33500
06-11-04 -5000 28500
06-11-06 7200 35700
06-11-11 11000 46700

--노이만재귀집합이용--

SELECT prc_date, A1.prc_amt,
(SELECT SUM(prc_amt)
FROM Accounts A2
WHERE A1.prc_date >= A2.prc_date ) AS onhand_amt
FROM Accounts A1
ORDER BY prc_date;

--결과--

PRC_DATE PRC_AMT ONHAND_AMT
-------- ---------- ----------
06-10-26 12000 12000
06-10-28 2500 14500
06-10-31 -15000 -500
06-11-03 34000 33500
06-11-04 -5000 28500
06-11-06 7200 35700
06-11-11 11000 46700

이번에는 3행단위로 누적하는 이동누적을 구해보자

--OLAP함수 이용--

SELECT prc_date, prc_amt,
SUM(prc_amt) OVER (ORDER BY prc_date
ROWS 2 PRECEDING) AS onhand_amt
FROM Accounts;

--이동누적 구하기--

SELECT prc_date, A1.prc_amt,
(SELECT SUM(prc_amt)
FROM Accounts A2
WHERE A1.prc_date >= A2.prc_date
AND (SELECT COUNT(*)
FROM Accounts A3
WHERE A3.prc_date
BETWEEN A2.prc_date AND A1.prc_date ) <= 3 ) AS mvg_sum
FROM Accounts A1
ORDER BY prc_date;

--결과--

PRC_DATE PRC_AMT ONHAND_AMT
-------- ---------- ----------
06-10-26 12000 12000
06-10-28 2500 14500
06-10-31 -15000 -500
06-11-03 34000 21500
06-11-04 -5000 14000
06-11-06 7200 36200
06-11-11 11000 13200

겹쳐지는 기간을 구하기

reserver
(
숙박자)

start_date
(
투숙일)

end_date
(
출발일)

김철수

2006-10-26

2006-10-27

이영희

2006-10-28

2006-10-31

박순희

2006-10-31

2006-11-01

최민철

2006-11-03

2006-11-04

송영수

2006-11-03

2006-11-05

고민수

2006-11-06

2006-11-06

위의 테이블은 어느 호텔의 객실 예약상황을 나타내는 표이다. 위 테이블을 이용해서 예약일이 겹치는 기간을 구해보자

SELECT reserver, start_date, end_date
FROM Reservations R1
WHERE EXISTS
(SELECT *
FROM Reservations R2
WHERE R1.reserver <> R2.reserver /* 자신이외의 손님과 비교 */
AND ( R1.start_date BETWEEN R2.start_date AND R2.end_date /* 条件(1):개시일이 다른 기간내에 있음 */
OR R1.end_date BETWEEN R2.start_date AND R2.end_date)); /* 条件(2):종료일이 다른 기간내에 있음 */

--결과--

RESERVER START_DATE END_DATE
--------------------------- ------------ -----------
이영희 06-10-28 06-10-31
박순희 06-10-31 06-11-01
송영수 06-11-03 06-11-05
최민철 06-11-03 06-11-04

위 테이블에서 최민철씨의 투숙일이 3일이 아닌 4일이면 어떻게 될까? 위의 SQL을 이용하면 결과에 송영수씨는 제외된다. 송영수씨의 투숙일과 출발일이 다른 손님들과 겹쳐지지 않게 되기 때문이다. 즉, 위의 쿼리는 상대의 기간을 완전히 포함하고 있는 기간은 선택되지 않는다는 것이다.

이런 기간을 구하기 위해 조건을 추가해보자.

--최민철씨의 투숙일 변경--

update reservations
set start_date = '2006-11-04'
where reserver = '최민철';

--위 쿼리를 그대로 이용--

SELECT reserver, start_date, end_date
FROM Reservations R1
WHERE EXISTS
(SELECT *
FROM Reservations R2
WHERE R1.reserver <> R2.reserver /* 자신이외의 손님과 비교 */
AND ( R1.start_date BETWEEN R2.start_date AND R2.end_date /* 条件(1):개시일이 다른 기간내에 있음 */
OR R1.end_date BETWEEN R2.start_date AND R2.end_date)); /* 条件(2):종료일이 다른 기간내에 있음 */

--결과(송영수씨가 제외됨)--

RESERVER START_DATE END_DATE
--------------------------- ------------ -----------
이영희 06-10-28 06-10-31
박순희 06-10-31 06-11-01
최민철 06-11-04 06-11-04

--상대를 전부 포함한 기간을 출력--

SELECT reserver, start_date, end_date
FROM Reservations R1
WHERE EXISTS
(SELECT *
FROM Reservations R2
WHERE R1.reserver <> R2.reserver
AND ((R1.start_date BETWEEN R2.start_date AND R2.end_date
OR R1.end_date BETWEEN R2.start_date AND R2.end_date)
OR (R2.start_date BETWEEN R1.start_date AND R1.end_date
AND R2.end_date BETWEEN R1.start_date AND R1.end_date)));
--결과--

RESERVER START_DATE END_DATE
--------------------------- ------------ -----------
이영희 06-10-28 06-10-31
박순희 06-10-31 06-11-01
송영수 06-11-03 06-11-05
최민철 06-11-04 06-11-04


[출처] SQL _ 상관서브쿼리|작성자 미우


'먹고살기 > Oracle' 카테고리의 다른 글

Sysdate  (0) 2011.06.02
SQL _ HAVING  (0) 2011.04.29
SQL _ HAVING_2  (0) 2011.04.29
SQL _ CASE식  (0) 2011.04.29
[Oracle] ROWNUM 사용 시 주의  (0) 2011.04.25
SQL _ HAVING_2 먹고살기/Oracle 2011. 4. 29. 16:32

아래 테이블은 소방대원의 상태를 나타내는 표이다. 팀 전원이 대기 상태일 때만 출동이 가능하다.

출동명령을 내릴 수 있는 팀을 찾아보자.

Teams

member
(대원)

team_id
(ID)

status
(상태)

1

대기

1

출동중

미크

1

대기

카렌

2

출동중

키스

2

휴가

3

대기

하트

3

대기

3

대기

베스

4

대기

알렌

5

출동중

로버트

5

휴가

마크

5

대기

「모든 멤버의 상태가 "대기중"이다」라는 조건은 전칭양화이므로 NOT EXISTS를 사용하면 된다.

SELECT team_id, member
FROM teams t1
WHERE
NOT EXISTS
(SELECT *
FROM teams t2
WHERE t1.team_id = t2.team_id
AND t2.status <> '대기')

--결과--

TEAM_ID MEMBER
-------- ------------
3 딕
3 하트
3 죤
4 베스

이것은 전칭양화와 존재양화간의 동치변환을 이용한 것이다.

「모든 멤버의 상태가 대기중이다」

= 「대기중이지 않은 멤버가 한명도 존재하지 않는다」

이 쿼리는 퍼포먼스면에서 뛰어나고 구체적인 팀멤버도 표시가능하다는 장점이 있다. 하지만 이중부정을 사용하기 때문에 직감적으로 알기 어려운 쿼리이기도 하다.

HAVING구를 사용하면 다음과 같이 간단하게 표현할 수 있다.

--전칭문을 집합으로 표현

SELECT team_id
FROM teams
GROUP BY team_id
HAVING count(*) = sum(CASE WHEN status = '대기'

THEN 1

ELSE 0 END);

----전칭문을 집합으로 표현 ②

SELECT team_id
FROM teams
GROUP BY team_id
HAVING max(status) = '대기'
AND min(status) = '대기'; ---
최대값과 최소값이 같다는 것은 그 집합은 한종류의 값밖에 없다는 것을 나타내는 것임

--결과--

team_id

-------

3

4

이번에는 출동가능멤버를 일람하는 쿼리를 만들어보자

SELECT team_id,
CASE WHEN max(status) = '대기' AND min(status) = '대기'
THEN '출동!'
ELSE '멤버부족' END AS status
FROM teams
GROUP BY team_id

--결과--

TEAM_ID STATUS
-------- ---
1 멤버부족
2 멤버부족
4 출동!
5 멤버부족
3 출동!

Materials

center
(거점)

receive_date
(반입일)

material
(자원)

서울

2007-4-01

주석

서울

2007-4-12

아연

서울

2007-5-17

알루미늄

서울

2007-5-20

아연

부산

2007-4-20

부산

2007-4-22

니켈

부산

2007-4-29

대구

2007-3-15

티탄

대구

2007-4-01

탄소강

대구

2007-4-24

탄소강

대구

2007-5-02

마그네슘

대구

2007-5-10

티탄

인천

200-5-10

아연

인천

2007-5-28

주석

위의 테이블에서 자원이 중복되어 있는 거점을 찾는 쿼리를 만들어보자.

--자원이 중복된 거점 선택

SELECT center
FROM materials
GROUP BY center
HAVING count(center) <> count(distinct material);

--결과--

CENTER
------------
서울
대구

--거점마다 중복여부 일람표시

SELECT center,
CASE WHEN count(center) <> count(distinct material)
THEN '중복있음'
ELSE '중복없음' END status
FROM materials
GROUP BY center;

--결과--

CENTER STATUS
------------ ---------
부산 중복없음
서울 중복있음
인천 중복없음
대구 중복있음

--중복이 있는 집합: EXISTS이용

SELECT center, material
FROM materials m1
WHERE
EXISTS
(SELECT *
FROM materials m2
WHERE m1.center = m2.center
AND m1.material = m2.material
AND m1.receive_date <> m2.receive_date);

--결과--

CENTER MATERIAL
------------ ------------
서울 아연
서울 아연
대구 티탄
대구 탄소강
대구 탄소강
대구 티탄

위테이블에서 원산국을 추가시킨 테이블을 이용해 (자원,원산국)의 2열로 봤을 때 중복되어 있는 거점을 선택하는 쿼리를 만들어보자.

Materials2

center
(
거점)

receive_date
(
반입일)

material
(
자원)

orgland
(
원산국)

서울

2007-04-01

주석

칠레

서울

2007-04-12

아연

타이

서울

2007-05-17

알루미늄

브라질

서울

2007-05-20

아연

타이

부산

2007-04-20

호주

부산

2007-04-22

니켈

남아프리카

부산

2007-04-29

인도

대구

2007-03-15

티탄

볼리비아

대구

2007-04-01

탄소강

칠레ㅔ

대구

2007-04-24

탄소강

아르헨티나

대구

2007-05-02

마그네슘

칠레

대구

2007-05-10

티탄

타이

인천

200-05-10

아연

미국

인천

2007-05-28

주석

러시아

COUNT함수가 인수로 쓸 수 있는 열은 한개밖에 없다. COUNT(material, orgland)라고는 쓸 수 없을 것이다. 어떻게 하면 될까? 한개밖에 인수로 쓸 수 없다면 강제로 인수를 한개로 만들면 될 것이다.

SELECT center
FROM materials2
GROUP BY center
HAVING count(material||orgland) <> count(distinct material||orgland);

--결과--

CENTER
------------
서울

--EXISTS를 사용하기

select distinct center
from materials2 m1
where exists
(select *
from materials2 m2
where m1.center = m2.center
and m1.material = m2.material
and m1.orgland = m2.orgland
and m1.receive_date <> m2.receive_date)

TestResults테이블을 이용해 아래 문제의 쿼리를 작성해보자.

TestResults

student_id
(학생ID)

class
(클래스)

sex
(성별)

score
(점수)

001

A

100

002

A

100

003

A

49

004

A

30

005

B

100

006

B

92

007

B

80

008

B

80

009

B

10

010

C

92

011

C

80

012

C

21

013

D

100

014

D

0

015

D

0

Q1.클래스의 75%이상의 학생이 80점이상인 클래스를 선택하시오

SELECT class
FROM testresults
GROUP BY class
HAVING count(*) * 0.75 <= sum(CASE WHEN score >= 80

THEN 1

ELSE 0 END);

--결과--

CLASS
-------
B

Q2.50점 이상을 받은 학생 중, 남자수가 여자수보다 많은 클래스를 선택하시오

SELECT class
FROM testresults
GROUP BY class
HAVING sum(CASE WHEN sex = '남' AND score >= 50
THEN 1
ELSE 0 END)
> sum(CASE WHEN sex = '여' AND score >= 50
THEN 1
ELSE 0 END);

--결과--

CLASS

--------

B

C

Q3. 여자의 평균점이 남자의 평균점보다 높은 클래스를 선택하시오.

SELECT class
FROM testresults
GROUP BY class
HAVING avg(CASE WHEN sex = '남'
THEN score
ELSE null END)
< avg(CASE WHEN sex = '여'
THEN score
ELSE null END)

--결과--

CLASS

-------

A

아래 테이블을 이용해서 수학이 80점 이상이고 국어가 50점 이상인 학생을 찾는 쿼리를 작성해보자.

TestScores

student_id
(
학생ID)

subject
(
과목)

score
(
점수)

100

수학

100

100

국어

80

100

과학

80

200

수학

80

200

국어

95

300

수학

40

300

국어

90

300

사회

55

400

수학

80

SELECT student_id
FROM testscores
WHERE subject IN('수학','국어')
GROUP BY student_id
HAVING SUM(CASE WHEN subject = '수학' AND score >= 80 THEN 1
WHEN subject = '국어' AND score >= 50 THEN 1
ELSE 0 END) = 2

--결과--

STUDENT_ID
----------
100
200

HAVING구를 사용함에 있어 포인트를 한마디로 얘기하라면 "무엇으로 집합이라고 가정할 것인지에 착목하라"는 것이다. SQL에 있어서 무엇을 집합으로 가정할 것인지의 기준은 집합을 이루는 것이 현실세계에서 어떤 레벨인지는 상관없고, 단지 테이블에서 어떻게 표현되는지만이 중요하다. 어떤 실체가 때에 따라서는 요소가 되기도 하고 집합이 되기도 하는 것이다. 실체 한개당 한행만이 할당된다면 이 실체는 집합의 요소로써 취급되고 있는 것이다. 이때는 조건을 지정할 때 WHERE구를 사용하면 된다. 한편 한개당 복수행이 할당된다면 집합으로 취급되고있다는 증거이다. 그렇다면 HAVING구를 사용하면 된다.

집합의 성질을 조사하기 위한 대표적인 조건을 정리해두자. 이 조건은 HAVING구 혹은 SELECT구의 CASE식에서 사용할 수 있다.

집합의 성질을 찾기 위한 조건의 사용법 일람

조건식

용도

1

COUNT(DISTINCT col) = COUNT(col)

col값이 유일하다

2

COUNT(*) = COUNT(col)

col에 NULL이 존재하지 않는다

3

COUNT(*) = MAX(col)

col는 결번이 없는 연번(개시값은 1)

4

COUNT(*) = MAX(col) - MIN(col) + 1

col는 결번이 없는 연번(개시값은 임의의 정수)

5

MIN(col) = MAX(col)

col가 한개만의 값을 가지던가 아니면 NULL이다

6

MIN(col) * MAX(col) > 0

모든 col_x의 기호가 동일하다

7

MIN(col) * MAX(col) < 0

최대값은 양수고 최소값은 음수이다

8

MIN(ABS(col)) = 0

col은 적어도 한개의 0를 포함한다

9

MIN(col - 정수 ) = -MAX(col - 정수)

col의 최대값과 최소값은 지정한 정수에서 값은 간격으로 떨어져있다

[출처] SQL _ HAVING_2|작성자 미우


'먹고살기 > Oracle' 카테고리의 다른 글

SQL _ HAVING  (0) 2011.04.29
SQL _ 상관서브쿼리  (0) 2011.04.29
SQL _ CASE식  (0) 2011.04.29
[Oracle] ROWNUM 사용 시 주의  (0) 2011.04.25
오라클 데이터 타입  (0) 2011.04.22