상속 (Inheritance)

- 기존의 클래스를 재사용해서 새로운 클래스를 작성하는 것.

- 두 클래스를 부모와 자식으로 관계를 맺어주는 것

- 자손은 조상의 모든 멤버를 상속받는다. (생성자, 초기화 블럭 제외)

- 자손의 멤버 개수는 조상보다 같거나 많다.

- 자손의 변경은 조상에 영향을 미치지 않는다. 

  자식이 새로운 멤버를 추가해도 부모클래스에는 영향이 없다.

 

class  자식클래스 extends 부모클래스 {

                     //

}

 

public class Point {  //2차원 좌표의 한 점 (x,y)
	int x;
	int y;
}

//3차원 좌표

1)
class Point3D { //Point 클래스와 전혀 연관 없음
	int x;
	int y;
	int z;
}


2)   // 자식 	        부모
class Point3D extends Point { //상속관계로 영향을 받는다.
	int z;
}

Point3D p = new Point3D(); // 결과는 똑같다.

 

예제)

public class Tv {
	boolean power;     //전원상태(on/off)
	int channel; 
	
	void power ()      { power = !power;}
	void channelUp()   { ++channel; }
	void channelDown() { --channel; }
	
}

class SmartTv extends Tv {  //SmartTv는 Tv에 자막(caption) 보여주는 기능
	boolean caption;	    //caption상태 (on/off)
	void displayCaption(String text){
		if(caption) {	    //caption상태가 true(on) 일때만 text를 보여준다.
			System.out.println(text);
		}
	}
	
}

class Ex_7{
	// 메인 메서드 실행
	public static void main(String[] args) {
		SmartTv stv = new SmartTv();
		stv.channel = 10;    // 상속받은 부모의 변수를 쓸 수 있다
		stv.channelUp();     // 싱석받은 부모의 메서드를 쓸 수 있다.
		System.out.println(stv.channel);
		stv.displayCaption("Hello, world"); //자신이 가진 메서드 실행
		stv.caption = true;
		stv.displayCaption("Helle, world");
	}

클래스의 관계 - 상속과 포함

 

포함

클래스의 멤버로 참조변수를 선언하는 것

 

 

 

class Car {
	// 포함
    Engine e = new Engine; 
    Door[] d = new Door[4];

}

 

클래스 간의 관계 결정하기

 

상속관계 : A은 B이다 (is - a)

포함관계 : A는 B를 가지고 있다 (has - a)

 

원은 점이다. (상속)

원은 점을 가지고 있다. (포함)=> 더 자연스러움 

90% 포함이다.

상속은 꼭 필요할때만 쓰자


다형성

- 조상타입 참조변수로 자손타입객체를 다루는 것

 

// 기존
     TV t = new TV();  // 타입 일치
SmartTv s = new SmartTv();

// 다형성
     TV t = new SmartTv();  //타입 불일치 해도 OK
    (부모)       (자식)

 

▶ 객체와 참조변수의 타입이 일치할 때와 일치하지 않을 때의 차이?

     = 조상타입의 참조변수로 자손타입의 객체를 다룰 수 있는 것이 다형성.

 

※ 자손타입의 참조변수로 조상타입의 객체를 가리킬 수 없다.

     TV     t  =  new SmartTv(); // OK
(부모멤버 5개)  <  (자식멤버 7개)
    
  SmartTv   t  =  new Tv();   //에러!!
(자식멤버 7개)  >  (부모멤버 5개)

 

 

참조변수의 타입은 인스턴스의 타입과 반드시 일치해야 하는가?

=> 일치하는 것이 보통이지만 일치 하지 않을 수도 있다.

 

참조변수가 조상타입일 때와 자손타입일때의 차이?

=> 참조변수로 사용할 수 있는 멤버 갯수가 달라짐.

 

자손타입의 참조변수로 조상타입의 객체를 가리킬수 있는지?

=> NO !!


참조변수의 형변환

: 사용할 수 있는 멤버의 갯수를 조절하는 것.

 

- 조상,자손 관계의 참조변수는 서로 형변환 가능

- 형제끼리는 형변환 불가

 

class Car { // 멤버 4개   //  .water() 없음	
	String cololr;
	int door;
	
	void drive() { System.out.println("drive~~");}	
	void stop() {System.out.println("stop~~~");}	
}

class FireEngine extends  Car {	
	void water() {System.out.println("water~~~");}
}
public static void main(String[] args) {		
		Car car = null;
		FireEngine fe = new FireEngine();
//		FireEngine fe2 = null;
		FireEngine fe2 = (FireEngine)car; // 조상 -> 자손으로 형변환
		Car car2 = (Car)fe2;			  // 자손 -> 조상으로 형변환
//		car2.drive(); // 에러 : NullPointerException
		//car2는 객체생성을 안해서 값이 null이기 때문에!!
		//형변환 할때 실제 인스턴스(객체)가 무엇인지 중요하고 
        //그것을 넘지 않는게 중요하다.
		
		fe.water();
		car = fe;  // car = (Car)fe 생략가능
//		car.water(); //에러 Car타입으로는  .water() 사용 불가
		fe2 = (FireEngine)car;  // 자손타입 <- 조상타입 형변환 ()생략불가
		fe2.water(); // FireEngine타입으로 쓸수 있음
		
		Car c = new Car();  // Car타입 객체 생성
		FireEngine fe3 = (FireEngine)c; // 조상 -> 자손으로 형변환인데 컴파일 통과.
		// Car 타입 c는 멤버가 4개, water()가 없음.
//		fe3.water();  // => 에러		
	}

컴파일 에러! Car 타입의 참조변수로는 water()를 호출할 수 없다.

 

※ 참조변수가 가리키는 객체(new)의 타입이 무엇인지 꼭 확인하자.


instanceof 연산자

 

1) 확인, 형변환 해도 되는지

2) 형변환

 

- 참조변수의 형변환 가능여부 확인에 사용. 가능하면 true 반환(조상-자손)

- instanceof의 연산결과가 true이면, 해당 타입으로 형변환이 가능.

System.out.println(fe instanceof Object);   // 결과 : true
System.out.println(fe instanceof Car);        // 결과 : true
System.out.println(fe instanceof FireEngine);   // 결과 : true

Object obj = (Object)fe;   // 형변환 가능
Car c = (Car)fe;   // 형변환 가능

자기 자신도 다 참(true), 조상에 대해서 다 참(true)이다.

 

참조변수의 형변환 왜함? (타입 일치시키려고)

= 참조변수(리모컨)을 변경함으로써 사용할 수 있는 맴버의 갯수를 조절하기 위해서

 

instanceof 언제 사용하는지?

참조변수를 형변환 하기전에 여부를 확인하기 위해


매개변수의 다형성

 

장점 

1) 다형적 매개변수

2) 하나의 배열로 여러종류 객체 다루기

 

참조형 매개변수는 메서드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.

 

class Product {
	int price;
	int bonusPoint;
	
	Product(int price){ // 생성자
		this.price = price;
		bonusPoint = (int)(price/10.0);  // 제품 가격의 10%
	}	
}
class Tv1 extends Product {
    Tv1 () {super(100);}       // 가격 : 100만원
	@Override
	public String toString() {return "TV";}
}
		
	
class Computer extends Product {
	Computer() { super(200);}   // 가격 200 만원
	@Override
	public String toString() {return "computer";}
}

class Buyer {
	int money=1000;
	int bonusPoint = 0;
	
	void buy(Product p) { //Product의 자손 Tv1, Computer 매개변수로 전달
		if (money < p.price) {
			System.out.println("잔액이 부족하여 물건으 살수 없습니다.");
			return;
		}
		money -= p.price;
		bonusPoint += p.bonusPoint;
		System.out.println(p + "을/를 구입하였습니다.");	
	}
}

public static void main(String[] args) {
		
    Buyer b = new Buyer();
//    buy(Product p)  제품구매(객체 생성)-> buy의 매개변수로 전달	
    b.buy(new Tv1()); // tv구매 :  
    b.buy(new Computer()); //Computer 구매
		
    System.out.println("현재 남은 돈은 " + b.money + "만원입니다");
    System.out.println("현재 보너스 점수는 " + b.bonusPoint +"점 입니다.");
}

Product p = new  Tv1();

b.buy(p);

= b.buy(new Tv1());

 

 


여러 종류의 객체를 하나의 배열로 다루기 (다형성의 장점)

 

: 조상타입의 배열에 자손들의 객체를 담을 수 있다.

= 하나의 배열에 여러 종류의 객체 저장

 

 

class Buyer2 {
	int money=1000;
	int bonusPoint = 0;
	Product[] cart = new Product[10];
	
	int i=0;
	
	void buy(Product p) {
		if (money < p.price) {
			System.out.println("잔액이 부족하여 물건으 살수 없습니다.");
			return;
		}
		money -= p.price;
		bonusPoint += p.bonusPoint;
		System.out.println(p + "을/를 구입하였습니다.");
		cart[i++] = p; // 카트배열에 객체 저장
	}
}

 

▶ Vector 클래스 : 가변배열 가능

public class Vecter extends AbstractList...

protected Object elementData[];

Object 배열 = 모든 종류의 객체 저장 가능

 

 


예제) Ex7_9

class Buyer3 {
	int money=1000;
	int bonusPoint = 0;
	Product2[] cart = new Product2[10];
    
	int i=0;
	
	void buy(Product2 p) {
		if (money < p.price) {
			System.out.println("잔액이 부족하여 물건으 살수 없습니다.");
			return;
		}
		money -= p.price;
		bonusPoint += p.bonusPoint;
		cart[i++] = p;
		System.out.println(p + "을/를 구입하였습니다.");
	}
	
	void summary() {
		int sum = 0;
		String itemList = "";
		
		for (int i = 0; i < cart.length; i++) {
			if(cart[i] == null) break;
			sum += cart[i].price;
			itemList += cart[i] + ", ";
		}
		System.out.println("구입하신 물품의 총금액은" + sum + "만원입니다.");
		System.out.println("구입하신 제품은" + itemList + "입니다.");
	}

Test

public static void main(String[] args) {
   Buyer3 b = new Buyer3();
		
   b.buy(new Tv2());
   b.buy(new Audio());
   b.buy(new Computer2());
   b.summary();	// cart배열 출력
	}

- 하나의 테이블에 2개 이상의 별칭을 부여하여 다른 테이블로 간주한 후 수행하는 조인

 

사용예) 회원테이블에서 '이혜나' 회원의 마일리지보다 많은 마일리지를 보유한 회원들을 조회하시오.
       Alias는 회원번호,회원명,마일리지
       -- 같은 멤버테이블에서 '이혜나'의 테이블과 다른 모든 회원테이블과 조인한다.
       -- 모든회원테이블은 이혜나의 값보다 많은 값을 가진다. 
       -- '=' 연산자 이외의 연산자 사용 //비동등조인 사용

 

 SELECT B.MEM_ID AS 회원번호,
                B.MEM_NAME AS  회원명,
                B.MEM_MILEAGE AS 마일리지
   FROM  MEMBER A, MEMBER B
WHERE  A.MEM_NAME='이혜나'
      AND B.MEM_MILEAGE > A.MEM_MILEAGE;  

-- 조인조건 : 모든 회원의 마일리지 > 이혜나의 마일리지(6500) => 결과 진현경 : 8700

EX) 오철희 회원(3700)  보다 많은 마일리지를 가진회원 : 이혜나, 구길동, 이진영, 진현경

 

 

22-11-28 ) 서브쿼리

 - SQL구문안에 포함된 또 다른 SQL 구문
  - 서브쿼리는 알려지지 않은 조건에 근거한 검색을 수행하는 경우 사용
  - 서브쿼리는 메인쿼리의 해당 절이 실행되기 전에 한번 실행 됨
  - 서브쿼리는 '( )' 안에 기술하며, 연산자와 함께 사용하는 경우 연산자 우측에 위치해야 함
  -- 예외 : insert/ create table문에 나오는 서브쿼리는 ()생략
  -- 연산자의 오른쪽에 와야한다.
  - 분류
    . 연관성 있는 서브쿼리/연관성 없는 서브쿼리
-- 연관성 있는 서브쿼리 : 메인쿼리와 서브쿼리에 사용된 테이블이 조인으로 연결된 경우 (대부분의 경우)


    . 일반서브쿼리(SELECT절)/인라인서브쿼리(FROM절)/중첩서브쿼리(WHERE절)
    -- 인라인 : 제일 먼저 실행되어야 할 절/서브쿼리가 먼저 실행되어야함. /자기가 스스로 실행되어야함.
    --         from절에 나오기 전에 결과가 나와야함 => 뷰
    -- select 의 결과가 뷰(익명뷰) / 뷰가 없어지기전에 이름을 부여하면 저장됨..
    -- WHERE절에 사용되는 서브쿼리 = 중첩서브쿼리. 연산자를 사용하면 서브쿼리를 연산자 오른쪽에 쓴다.

    . 단일행/다중행, 단일열/다중열
-- 행 : 다중행이냐 단일행이냐 중요함. 
    -- from 절에 사용된 서브쿼리 먼저 실행 => 그 다음 where절 실행 => select 절 실행 

 

1. 연관성 없는 서브쿼리(Noncorrelated Subquery)
  - 메인쿼리와 서브쿼리에 사용된 테이블이 조인으로 연결되지 않은 경우

 

 

사용예) 사원테이블에서 사원들의 평균 급여보다 많은 급여를 받은 사원들을 조회하시오.
       Alias는 사원번호,사원명,급여,평균급여

더보기

메인쿼리 : 사원테이블에서 사원번호,사원명,급여,평균급여
    SELECT EMPLOYEE_ID AS 사원번호,
           EMP_NAME AS 사원명,
           SALARY AS 급여,
           (SELECT ROUND(AVG(SALARY))
              FROM HR.EMPLOYEES) AS 평균급여
      FROM HR.EMPLOYEES
     WHERE SALARY>(평균급여:서브쿼리)

서브쿼리 : 평균급여
    SELECT AVG(SALARY)
      FROM HR.EMPLOYEES

결합
    SELECT EMPLOYEE_ID AS 사원번호,
           EMP_NAME AS 사원명,
           SALARY AS 급여,
           (SELECT ROUND(AVG(SALARY)) 
              FROM HR.EMPLOYEES) AS 평균급여
   -- WHERE절의 계산결과는 안남음.. 둘다 써먹으려면 FROM절에서..
      FROM HR.EMPLOYEES
     WHERE SALARY>(SELECT AVG(SALARY) --WHERE절의 서브쿼리는 연산자 우측에 기술
                     FROM HR.EMPLOYEES) -- WHERE절의 계산이 끝나면 없어짐
/*    
(SELECT ROUND(AVG(SALARY)) 
              FROM HR.EMPLOYEES) = > 158번 실행되어진다.
 => FROM절에 기술해서 1번만 실행될수 있다. */
 
    SELECT A.EMPLOYEE_ID AS 사원번호,
           A.EMP_NAME AS 사원명,
           A.SALARY AS 급여,            
           ROUND(B.ESAL) AS 평균급여  
      FROM HR.EMPLOYEES A, (SELECT AVG(SALARY) AS ESAL
                            FROM HR.EMPLOYEES)B  -- 1행1열의 결과만 나옴  
--         HR.EMPLOYEES A와 B를 비교
     WHERE A.SALARY>B.ESAL;  -- 비동등 조인
       


 -- 총무부에 상위부서는 없음
사용예) SAMPLE계정에서 부모부서코드가 NULL이 아닌 부서에 속한 사원정보를 조회하시오
       Alias는 사원번호,사원명,부서코드,직책코드

 

더보기

메인쿼리 :  
    SELECT EMPLOYEE_ID AS 사원번호,
           EMP_NAME AS 사원명,
           DEPARTMENT_ID AS 부서코드,
           JOB_ID AS 직책코드 
      FROM LHY93_SAMPLE.EMPLOYEES
     WHERE DEPARTMENT_ID=(서브쿼리 : 부모부서코드가 NULL이 아닌 부서)

서브쿼리 : 부모부서코드가 NULL이 아닌 부서
    SELECT DEPARTMENT_ID
      FROM LHY93_SAMPLE.DEPARTMENTS
     WHERE PARENT_ID IS NOT NULL
       
결합 : 
    SELECT DISTINCT EMPLOYEE_ID AS 사원번호,
           EMP_NAME AS 사원명,
           DEPARTMENT_ID AS 부서코드,
           JOB_ID AS 직책코드 
      FROM LHY93_SAMPLE.EMPLOYEES
     WHERE DEPARTMENT_ID IN(SELECT DEPARTMENT_ID
                             FROM LHY93_SAMPLE.DEPARTMENTS
                            WHERE PARENT_ID IS NOT NULL);

 

** EXISTS 연산자 사용
    - 연산자의 대상의 결과가 하나의 행이라도 존재하면 참(TRUE)을 반환
    - 단일행 연산자
    - EXISTS 우측의 서브쿼리 결과가 값은 연산과 무관(보통 SELECT절에 '1'을 사용)

더보기

  SELECT DISTINCT A.EMPLOYEE_ID AS 사원번호,
           A.EMP_NAME AS 사원명,
           A.DEPARTMENT_ID AS 부서코드,
           A.JOB_ID AS 직책코드 
      FROM LHY93_SAMPLE.EMPLOYEES A
     WHERE EXISTS (SELECT 1  -- '1' = 의미 없는 1. / EXISTS의 결과가 하나라도 있음 TRUE
                                     FROM LHY93_SAMPLE.DEPARTMENTS B
                                  WHERE B.PARENT_ID IS NOT NULL
                                        AND A.DEPARTMENT_ID=B.DEPARTMENT_ID); -- 조인

-- EXISTS를 사용하면 연관성 없는 서브쿼리가 연관성 있는 서브쿼리로 바뀜 

 

사용예) HR계정의 직무변동테이블(JOB_HISTORY)의 부서의 부서코드,부서명,책임사원명을 조회하시오

 

더보기

메인쿼리 : 부서코드,부서명,책임사원명
    SELECT A.DEPARTMENT_ID AS 부서코드,
           A.DEPARTMENT_NAME AS 부서명,
           B.EMP_NAME AS 책임사원명
      FROM HR.DEPARTMENTS A, HR.EMPLOYEES B
     WHERE A.MANAGER_ID=B.EMPLOYEE_ID  
     -- 사원이름 꺼내기 위해 책임사원 ID = 사원테이블의 사원ID
       AND A.DEPARTMENT_ID=(서브쿼리 : 직무변동테이블 JOB_HISTORY의 부서코드)
       
서브쿼리 : 직무변동테이블 JOB_HISTORY의 부서코드
    SELECT DEPARTMENT_ID
     FROM HR.JOB_HISTORY
     
결합 :
     SELECT A.DEPARTMENT_ID AS 부서코드,
           A.DEPARTMENT_NAME AS 부서명,
           B.EMP_NAME AS 책임사원명
      FROM HR.DEPARTMENTS A, HR.EMPLOYEES B
     WHERE A.MANAGER_ID=B.EMPLOYEE_ID  
       AND A.DEPARTMENT_ID IN(SELECT DEPARTMENT_ID 
                                FROM HR.JOB_HISTORY)
     ORDER BY 1;   
    -- IN 연산자는 중복 제거를 한다. (DISTINCT와 같음)
    -- 연관성 없는 서브쿼리

 

 

더보기

    SELECT A.DEPARTMENT_ID AS 부서코드,
           A.DEPARTMENT_NAME AS 부서명,
           B.EMP_NAME AS 책임사원명
      FROM HR.DEPARTMENTS A, HR.EMPLOYEES B
     WHERE A.MANAGER_ID=B.EMPLOYEE_ID  -- 조건을 만족하는 값 11개(NULL값 버림)
       AND EXISTS (SELECT 1  
                                  FROM HR.JOB_HISTORY C
                               WHERE C.DEPARTMENT_ID=A.DEPARTMENT_ID)
     -- EXISTS를 사용하면 WHERE절이 반드시온다
     ORDER BY 1;  

 

(일반쿼리 사용) -- SELECT절에 서브쿼리를 사용한 경우

더보기

    SELECT DISTINCT A.DEPARTMENT_ID AS 부서코드,
          (SELECT DEPARTMENT_NAME
             FROM HR.DEPARTMENTS B 
    -- 서브쿼리를 벗어나면 값을 잃어버리기 때문에 다른 서브쿼리에 테이블 별칭 같이써도 됨
            WHERE A.DEPARTMENT_ID=B.DEPARTMENT_ID) AS 부서명,
          (SELECT C.EMP_NAME
             FROM HR.DEPARTMENTS B, HR.EMPLOYEES C
            WHERE A.DEPARTMENT_ID=B.DEPARTMENT_ID
              AND B.MANAGER_ID=C.EMPLOYEE_ID) AS 책임사원명
      FROM HR.JOB_HISTORY A
      ORDER BY 1;

 

사용예) 사원테이블에서 본인이 속한 부서의 평균급여보다 많은 급여를 받는 사원정보를 조회하시오.
       Alias는 사원번호,사원명,부서번호,부서명,부서평균급여,급여

 

더보기

 SELECT A.EMPLOYEE_ID AS 사원번호,
           A.EMP_NAME AS 사원명,
           A.DEPARTMENT_ID AS 부서번호,
           B.DEPARTMENT_NAME AS 부서명,
           (SELECT ROUND(AVG(C.SALARY))
             FROM HR.EMPLOYEES C
            WHERE C.DEPARTMENT_ID=A.DEPARTMENT_ID
         GROUP BY C.DEPARTMENT_ID) AS 부서평균급여,
           A.SALARY AS 급여
      FROM HR.EMPLOYEES A, HR.DEPARTMENTS B
     WHERE A.SALARY>(SELECT C.CASL 
                                        FROM (SELECT DEPARTMENT_ID, 
                                                                    AVG(SALARY) AS CASL      
                                                        FROM HR.EMPLOYEES                   
                                                GROUP BY DEPARTMENT_ID)C
                                      WHERE A.DEPARTMENT_ID=C.DEPARTMENT_ID)
       AND A.DEPARTMENT_ID=B.DEPARTMENT_ID
    ORDER BY 3, 6 DESC;

 

 

JOIN


  - 관계형 데이터베이스의 특징인 관계(Relationship)를 이용한 연산
  - 테이블의 정규화 과정을 거치면 자료가 여러 테이블에 분산되어 저장되고 이러한 자료를
    왜래키관계를 이용하여 조회할 수 있는 연산을 조인이라고 함.
  - 종류
    . 외부조인(Outer Join), 내부조인(Inner Join)
    /* 조인조건을 만족하는 것만 : 내부조인(부모자식테이블에 자료가 있는것만 씀)
     외부조인 : 여러 테이블에서 한쪽에는 데이터가 있고, 다른 쪽에는 데이터가 없는 경우 

                       데이터가 있는 쪽 테이블의 내용을 모두 출력하는 것.
                       (자료의 종류가 많을 때 ) 많은 쪽을 기준으로 조인 하는 것. */
       
    . 일반조인, ANSI JOIN
    . 동등조인, 비동등조인, 셀프조인, Cartesian Product 등 -- 대부분은 동등조인
--일반조인 : DBMS 회사별로 제공되는 조인형식 / ANSI JOIN : 미국표준위원회에서 정한 조인문 형식
--동등조인 : '='연산자가 사용된 조인 (가장 일반적인 조인형식)

 

 

--테이블이 2개가 사용되면 조인조건은 적어도 1개 이상
--조건이 기술되어져야해서 WHERE절 필수!

 

 


--  카타시안
 1. Cartesian Product
   - 조인조건이 없거나 조인조건이 잘못된 경우
   - n행 m열의 테이블과 a행 b열의 테이블이 카타시안 곱이 수행되면 최악의 경우
     (조인 조건이 없는 경우) n x a 행, m + b 열의 결과를 반환함
   - 반드시 필요한 경우를 제외하고 수행에서는 안됨

(사용형식-일반조인)

 SELECT 컬럼List
   FROM 테이블명1 [별칭1], 테이블명2 [별칭2] [, 테이블명3 [별칭3],...]
 [WHERE 조인조건];




(사용형식-ANSI조인)

SELECT 컬럼List
  FROM 테이블명1 [별칭1]
 CROSS JOIN 테이블명2 [별칭2]  [ON 조인조건]
[CROSS JOIN 테이블명3 [별칭3]] [ON 조인조건]
                    :
[WHERE 조인조건];


    


사용예)일반조인

 SELECT COUNT(*) 
   FROM PROD,BUYPROD,CART;  
-- PROD,BUYPROD,CART테이블을 Cartesian Product 
-- 조인했더니 2267064개의 행이 만들어짐



사용예)ANSI조인

 SELECT COUNT(*)
   FROM PROD
  CROSS JOIN BUYPROD
  CROSS JOIN CART;   -- 결과 : 2267064







 2. 내부조인
   - 조인조건을 만족하는 데이터만 결과로 반환하고 조인조건을 만족하지 않은 자료는 무시
   1) 동등조인(Equi Join)
     - 조인조건에 '=' 연산자를 사용한 조인
     - 대부분 내부 조인이 이에 속함
     
(사용형식-일반조인)

 SELECT 컬럼List
   FROM 테이블명1 [별칭1], 테이블명2 [별칭2] [, 테이블명3 [별칭3],...]
  WHERE [별칭1].컬럼명=[별칭2].컬럼명
    AND
   [AND 일반조건]
      . 사용된 테이블이 n개 일때 조인조건은 적어도 n-1개 이상이어야 함
      . 일반조건과 조인조건은 AND로 연결되며 기술 순서는 실행과 관계없음


      

(사용형식-ANSI조인) -- FROM 절에 테이블명 딱 1개만 나옴

 SELECT 컬럼List
   FROM 테이블명1 [별칭1]
  INNER JOIN 테이블명2 [별칭2] ON ([별칭1].컬럼명=[별칭2].컬럼명[AND 일반조건1])
 [INNER JOIN 테이블명3 [별칭3] ON ([별칭].컬럼명=[별칭3].컬럼명[AND 일반조건2])]
         :
 [WHERE 일반조건]
  . '테이블명1'과 '테이블명2'는 반드시 직접 조인 가능한 관계이여야 함
  . '일반조건1'은 '테이블명1'과 '테이블명2'에 관련된 조건이어야 함
  . '테이블명3' 부터는 '테이블명1'과 '테이블명2'의 조인 결과와 조인
  . 'WHERE 일반조건' : 모든 테이블에 공통적으로 부여되는 조건 기술


--일반 조건1은 테이블명2에 관련된 조건
--일반 조건2는 테이블명3에 관련된 조건
      
--거래처 별로 매입집계를 구할수 있나? 근데 공유하는 공통의 컬럼이 없음... 
--중간에 양쪽테이블에 공유하는 간접테이블로 연결해야함
--테이블1이 : BUYER 일때 테이블2에는 BUYPROD여서는 안된다(공유하는 컬럼이 없음)
--테이블2는 반드시 PROD이어야한다.

 

 

 

사용예) 사원테이블에서 2016년 1월 이후에 입사한 사원정보를 조회하시오
        Alias는 사원번호,사원명,부서번호,부서명,입사일

(일반 조인)
 SELECT A.EMPLOYEE_ID AS 사원번호,
        A.EMP_NAME AS 사원명,
        A.DEPARTMENT_ID AS 부서번호,
        B.DEPARTMENT_NAME AS 부서명,
        A.HIRE_DATE AS 입사일
   FROM HR.EMPLOYEES A, HR.DEPARTMENTS B
  WHERE A.DEPARTMENT_ID=B.DEPARTMENT_ID  -- 조인조건
    AND A.HIRE_DATE>=TO_DATE('20160201') -- 일반조건
ORDER BY 3;


  -- 조인조건 A테이블의 부서코드는 왜래키 / B테이블의 부서코드는 기본키
  -- 부서번호가 없는 외부직원이 존재하면 조인조건을 만족하지 않은 데이터는 버림

 

  
(ANSI조인)

 SELECT  A.EMPLOYEE_ID AS 사원번호,
         A.EMP_NAME AS 사원명,
         A.DEPARTMENT_ID AS 부서번호,
         B.DEPARTMENT_NAME AS 부서명,
         A.HIRE_DATE AS 입사일
   FROM HR.EMPLOYEES A
  INNER JOIN HR.DEPARTMENTS B ON (A.DEPARTMENT_ID=B.DEPARTMENT_ID
    AND A.HIRE_DATE>=TO_DATE('20160201')) 
  ORDER BY 3;
 SELECT  A.EMPLOYEE_ID AS 사원번호,
         A.EMP_NAME AS 사원명,
         A.DEPARTMENT_ID AS 부서번호,
         B.DEPARTMENT_NAME AS 부서명,
         A.HIRE_DATE AS 입사일
    FROM HR.EMPLOYEES A
   INNER JOIN HR.DEPARTMENTS B ON (A.DEPARTMENT_ID=B.DEPARTMENT_ID)
   WHERE A.HIRE_DATE>=TO_DATE('20160201')
   ORDER BY 3;

   

사용예) 사원테이블에서 부서별 2016년 1월 이후에 입사한 사원의 수를 조회하시오
              Alias는 부서번호,부서명,사원수이고 부서코드순으로 출력

 

(일반 조인)

 SELECT A.DEPARTMENT_ID AS 부서번호,
        B.DEPARTMENT_NAME AS 부서명,
        COUNT (*) AS 사원수
   FROM HR.EMPLOYEES A, HR.DEPARTMENTS B 
  WHERE A.HIRE_DATE>TO_DATE('20160131') -- 일반조건
    AND A.DEPARTMENT_ID=B.DEPARTMENT_ID -- 조인조건
  GROUP BY A.DEPARTMENT_ID, B.DEPARTMENT_NAME
  ORDER BY 1;


--GROUP BY A.DEPARTMENT_ID, B.DEPARTMENT_NAME
--부서가 같은것 끼리 모으고, 부서이름이 같고있는 것 끼리 모으고 조인

 


(ANSI조인 조인)

SELECT A.DEPARTMENT_ID AS 부서번호,
       B.DEPARTMENT_NAME AS 부서명,
       COUNT (*) AS 사원수
  FROM HR.EMPLOYEES A
 INNER JOIN HR.DEPARTMENTS B ON( A.HIRE_DATE>TO_DATE('20160131')
   AND A.DEPARTMENT_ID=B.DEPARTMENT_ID) 
 GROUP BY A.DEPARTMENT_ID, B.DEPARTMENT_NAME
 ORDER BY 1;

 

 

사용예) 2020년 월별 제품별 매입집계를 조회하시오
       Alias는 월,제품코드,제품명,매입수량,매입금액
 

(일반조인)

 SELECT EXTRACT(MONTH FROM B.BUY_DATE) AS 월,
        B.BUY_PROD AS 제품코드,
        A.PROD_NAME AS 제품명,
        SUM(B.BUY_QTY) AS 매입수량,  -- 매입집계를 구하시오가 있으니 SUM해야한다. 
        SUM(B.BUY_QTY*A.PROD_COST) AS 매입금액   -- 매입단가는 PROD테이블에서 찾기
   FROM PROD A, BUYPROD B
  WHERE A.PROD_ID=B.BUY_PROD -- 조인조건
    AND EXTRACT(YEAR FROM B.BUY_DATE)=2020  -- 일반조건 : 날짜함수
  GROUP BY EXTRACT(MONTH FROM B.BUY_DATE),B.BUY_PROD,A.PROD_NAME
  ORDER BY 1;

-- SUBSTR(BUY_DATE) => X       //     현재 BUY_DATE은 날짜타입으로 SUBSTR(문자열)으로 오류난다.

 

 

(ANSI조인)

 SELECT EXTRACT(MONTH FROM B.BUY_DATE) AS 월,
        B.BUY_PROD AS 제품코드,
        A.PROD_NAME AS 제품명,
        SUM(B.BUY_QTY) AS 매입수량,  
        SUM(B.BUY_QTY*A.PROD_COST) AS 매입금액  
   FROM PROD A
  INNER JOIN BUYPROD B ON(A.PROD_ID=B.BUY_PROD)
  WHERE EXTRACT(YEAR FROM B.BUY_DATE)=2020
  GROUP BY EXTRACT(MONTH FROM B.BUY_DATE),
           B.BUY_PROD, A.PROD_NAME
  ORDER BY 1;

 

 

 

사용예) 2020년 상품들의 분류별 매출집계를 조회하시오 
       Alias는 분류코드,분류명,판매금액 
       -- LPROD = 분류 // LPROD가 제일 상위 테이블이다.
       -- LPROD_GU가 기본키이다.

 

(일반조인)

    SELECT B.PROD_LGU AS 분류코드,
           C.LPROD_NM AS 분류명,
           SUM(A.CART_QTY*B.PROD_PRICE) AS 판매금액         
      FROM CART A, PROD B, LPROD C
     WHERE A.CART_PROD=B.PROD_ID  -- 상품코드가 서로 같아야 단가를 가져올수 있다.
       AND B.PROD_LGU=C.LPROD_GU -- 분류가 있는것끼리 모으려면 그룹바이
       AND SUBSTR(A.CART_NO,1,4)='2020' -- 문자열
     GROUP BY B.PROD_LGU,C.LPROD_NM
     ORDER BY 1;

 

(ANSI조인)

  SELECT B.PROD_LGU AS 분류코드,
         C.LPROD_NM AS 분류명,
         SUM(A.CART_QTY*B.PROD_PRICE) AS 판매금액         
    FROM CART A   -- CART A, 다음엔  PROD B이어야한다.
   INNER JOIN PROD B ON(A.CART_PROD=B.PROD_ID 
         AND SUBSTR(A.CART_NO,1,4)='2020')
   INNER JOIN LPROD C ON( B.PROD_LGU=C.LPROD_GU)  
   GROUP BY B.PROD_LGU,C.LPROD_NM
   ORDER BY 1;

 

 

 


 

 

숙제] 사원테이블에서 미국이외에 위치한 부서에 근무하는 사원들을 조회하시오
     Alias 는 사원명,부서번호,부서명,부서주소이며 부서주소는 거리주소 도시 주, 국가명 (hr테이블 4~5개 사용)
     형식으로 출력할 것

DEPARTMENTS 테이블의  LOCATION_ID : 위치 코드 값
LOCATIONS 테이블의 LOCATION_ID (기본키)
COUNTRIES 국가 테이블 COUNTRY_ID 나라

- 필요한 테이블 - 
HR.EMPLOYEES
HR.DEPARTMENTS
HR.COUNTRIES
HR.LOCATIONS

 SELECT E.EMP_NAME AS 사원명,
        E.DEPARTMENT_ID AS 부서번호,
        D.DEPARTMENT_NAME AS 부서명,
        L.STREET_ADDRESS||' '||L.CITY||' '
        ||L.STATE_PROVINCE||','||C.COUNTRY_NAME AS 부서주소
   FROM HR.EMPLOYEES E, HR.DEPARTMENTS D, 
        HR.LOCATIONS L, HR.COUNTRIES C
  WHERE E.DEPARTMENT_ID=D.DEPARTMENT_ID
    AND D.LOCATION_ID=L.LOCATION_ID
    AND L.COUNTRY_ID=C.COUNTRY_ID
    AND C.COUNTRY_ID != 'US';

 

 

 

 

 

 

 

 

 

 

 

 

 


** 재고수불테이블 생성
  1) 테이블명 : REMAIN
  2) 컬럼명세



       
-- REMAIN_J_00 기초재고  / DEFAULT VALUE 값 ?
-- REMAIN_I 입고수량   /  REMAIN_O  출고수량
-- REMAIN_J_99 기말고 = 현재 창고에 있는 재고  // 현재고 = 기초재고 + 입고재고 - 판매재고
-- REMAIN_DATE 날짜 타입 데이터 / 업데이트 되어진 날짜
    
        
        

 

 

 

 

새테이블 만들기

 

왜래키 설정하기

 

종속삭제를 선택한경우 ON DELETE CASCADE


  - NVL, NVL2, NULLIF 등이 제공됨
 
 1. IS NULLIS NOT NULL
   . NULL값은 '='연산자로 동등성 평가가 불가능함
   . NULL의 평가를 위한 연산자로 IS, IS NOT 연산자가 제공됨

  

사용예) 상품테이블에서 상품의 색상(PROD_COLOR)이 

              NULL인 제품의 제품코드,제품명,매입단가를 조회하시오

SELECT  PROD_ID AS 제품코드,
        PROD_NAME AS 제품명,
        PROD_COST AS 매입단가
  FROM  PROD
 WHERE PROD_COLOR IS NULL;

 

 

 

 

 

 2. NVL(expr, val)
   . 'expr' 값이 NULL이면 'val'를 반환하고 NULL이 아니면  'expr'값을 반환
   . 'expr'과 'val'은 같은 데이터 타입 이어야 함

 

사용예) 2020년 7월 모든(=OUTTER JOIN 외부조인) 회원별 구매현황을 조회하시오 
        -- '모든' 이라는 수식어가 붙으면 OUTTER JOIN 외부조인이다.
       Alias는 회원번호,회원명,구매수량합계

 SELECT B.MEM_ID AS 회원번호,
        B.MEM_NAME AS 회원명,
        SUM(A.CART_QTY) AS 구매수량합계
   FROM CART A
  RIGHT OUTER JOIN MEMBER B ON(A.CART_MEMBER=B.MEM_ID
    AND A.CART_NO LIKE '202007%')
  GROUP BY B.MEM_ID,B.MEM_NAME
  ORDER BY  1;

 

※ NVL로 null 값을 0으로

  SELECT B.MEM_ID AS 회원번호,
         B.MEM_NAME AS 회원명,
         NVL(SUM(A.CART_QTY),0) AS 구매수량합계
    FROM CART A
   RIGHT OUTER JOIN MEMBER B ON(A.CART_MEMBER=B.MEM_ID
     AND A.CART_NO LIKE '202007%')
   GROUP BY B.MEM_ID,B.MEM_NAME
   ORDER BY  1;

 

 


사용예) 2020년 7월 모든(=OUTTER JOIN 외부조인) 회원별 구매현황을 조회하시오 
       Alias는 회원번호,회원명,구매수량합계 이며 구매수량이 없으면 '구매정보없음'을 출력

 

       

※ 하지만 '구매수량합계'의 값은 문자열이다.(TO_CHAR)

SELECT B.MEM_ID AS 회원번호,
       B.MEM_NAME AS 회원명,
       NVL(SUM(A.CART_QTY),'구매정보없음') AS 구매수량합계
   --  오류 :'expr'과 'val'은 같은 데이터 타입 이어야 함
  FROM CART A
 RIGHT OUTER JOIN MEMBER B ON(A.CART_MEMBER=B.MEM_ID
   AND A.CART_NO LIKE '202007%')
 GROUP BY B.MEM_ID,B.MEM_NAME
 ORDER BY  1;
-------------------------------------------------------------    
SELECT B.MEM_ID AS 회원번호,
       B.MEM_NAME AS 회원명,
       NVL(TO_CHAR(SUM(A.CART_QTY),'9,999,999'),
       '구매정보없음') AS 구매수량합계
   --  오류 :'expr'과 'val'은 같은 데이터 타입 이어야 함
   -- 'expr' 을 문자열로 바꿔줘야함
  FROM CART A
  RIGHT OUTER JOIN MEMBER B ON(A.CART_MEMBER=B.MEM_ID
    AND A.CART_NO LIKE '202007%')
  GROUP BY B.MEM_ID,B.MEM_NAME
  ORDER BY  1;

 

 

 

 

3. NVL2(expr, v1,v2)
   . 'expr' 값이 NULL이면 v2를 반환하고, NULL이 아니면 v1을 반환
   . NVL을 확장한 개념(NVL을 NVL2로 변환가능)
   . v1과 v2는 같은 데이터 타입이어야 함
   
사용예) 상품테이블에서 제품의 제품코드,제품명,매입단가,색상을 조회하시오
       색상이 NULL이면 '색상정보 없음'을 출력하시오. NVL2와 NVL을 적용

(NVL 사용)
SELECT PROD_ID AS 제품코드,
       PROD_NAME AS 제품명,
       PROD_COST AS 매입단가,
       NVL(PROD_COLOR,'색상정보 없음')  AS 색상
  FROM PROD;
      
(NVL2 사용)
SELECT PROD_ID AS 제품코드,
       PROD_NAME AS 제품명,
       PROD_COST AS 매입단가,
       NVL2(PROD_COLOR,PROD_COLOR,
       '색상정보 없음')  AS 색상
  FROM PROD;

 

 

사용예) 사원테이블에서 사원들의 보너스를 계산하시오.
            보너스는 영업실적이 있으면 기본급여(SALARY)*영업실적이고, 영업실적이 없으면
            기본급여(SALARY)*10%이다.
            영업실적이 없으면 영업실적에 '실적없음'을 출력할 것.
            Alias는 사원번호,사원명,영업실적,기본급,보너스
      

SELECT EMPLOYEE_ID AS 사원번호,
       EMP_NAME AS 사원명,
       NVL(TO_CHAR(COMMISSION_PCT,'0.99'),'실적없음') AS 영업실적,
       SALARY AS 기본급,
       NVL2(COMMISSION_PCT,SALARY*COMMISSION_PCT,SALARY*0.1) AS 보너스          
  FROM HR.EMPLOYEES

 

 

 

 


 4. NULLIF(col1, col2)
   . col1과 col2를 비교하여 서로 같은 값이면 NULL을 반환하고 다른값이면 'col1'을 반환함

 

 

 

 

** 상품테이블에서 분류코드 'P301' 자료의 매출가격을 

    매입가격으로 조정하시오

 UPDATE PROD
    SET PROD_PRICE=PROD_COST
  WHERE PROD_LGU= 'P301';
-- 4개 행 이(가) 업데이트되었습니다.
  : P301이 포함한 제품이 4가지

 

 

사용예) 상품테이블에서 상품들의 매입가와 매출가를 조회하여 같은 값이면 비고란에 '단종예정상품'을,
        서로 다른 가격이면 판매이익을 조회하시오.
        Alias는 상품코드, 상품명,매입가격, 매출가격, 비고

 

 SELECT PROD_ID AS 상품코드, 
        PROD_NAME AS 상품명,
        PROD_COST AS 매입가격, 
        PROD_PRICE AS 매출가격, 
    -- 같은 값이면 '단종예정상품' /다른 값이면 판매이익
        NVL2(NULLIF(PROD_COST,PROD_PRICE),
        TO_CHAR(PROD_PRICE-PROD_COST,'9,999,999'), '단종예정상품') AS 비고           
   FROM PROD;

객체 지향언어

= 기존의 프로그래밍 언어에서 몇가지 새로운 규칙을 추가한 형태

 

1. 객체지향언어의 특징

  1) 코드의 재사용성이 높다.

  2) 코드의 관리가 용이하다.

  3) 신뢰성이 높은 프로그래밍을 가능하게 된다.

 

2. 클래스와 객체

    객체와 인스턴스

    클래스 = 설계도

    객체 = 제품

 

< 인스턴스 화 >

클래스로부터 객체를 만드는 과정

클래스 => 객체 생성 및 사용

 

1) 클래스 : 객체를 정의해 놓은 것, 객체의 설계도(틀)

  - 클래스의 정의 : 객체를 정의해 놓은 것

  - 클래스의 용도 : 클래스는 객체를 생성하는데 사용된다.

 

2) 객체 : 프로그래밍에서의 객체 : 클래스에 정의된 내용대로 메모리에 생성된 것

  - 객체의 정의 : 실제로 존재하는 것. 사물 또는 개념

  - 객체의 용도 : 객체가 가지고 있는 기능과 속성에 따라 다름

  - 유형의 객체 : 책상, 의자, 자동차, tv와 같은 사물

  - 무형의 객체 : 수학공식, 프로그램 에러와 같은 논리나 개념

 

 

클래스가 왜 필요한가? = 객체를 생성하기 위해

객체가 왜 필요한가? = 객체를 사용하기 휘해

객체를 사용한다는 것은? = 객체가 가진 속성과 기능을 사용하려고

 

2. 인스턴스의 생성과 사용

 1) 클래스 작성

 2) 객체 생성

 3) 객체 사용

 

Tv t;				//리모콘 생성 참조변수t 선언
t = new Tv();		//객체생성 = Tv인스턴스 생성
t.channel = 7;		//객체 사용 = 객체가 가진 멤버 사용
t.channelDown();	//객체 매서드 사용
System.out.println("현재 채널은" + t.channel + " 입니다.");

결과 = t.channel 의 값 = 6 

 

인스턴스는 참조변수를 통해서만 다룰수 있으며,

참조변수의 타입은 인스턴스의 타입과 일치해야 한다.


객체 배열

 

객체배열 == 참조변수 배열

객체 배열안에 객체가 저장되는 것은 아니고, 객체의 주소가 저장된다.

Tv tv1, tv2, tv3;
		
//tvArr 참조변수
Tv[] tvArr = new Tv[3]; 
//객체 배열 Tv타입 참조변수 3개 생성 / 객체 배열 == 참조변수 배열
		
Tv t1 = new Tv();
Tv t2 = new Tv();
Tv t3 = new Tv();

참조변수 배열(객체배열) 을 생성하고

객체배열의 각 요소에 저장해야 한다.

(같은 타입만 저장해야 하며, 하나의 배열로 여러 종류의 객체를 저장하려면 다형성을 배워야 함)

 

 

 객체 배열은 참조변수들을 하나로 묶은 참조변수 배열이다.

 

 

 

 

클래스의 정의

1) 설계도

2) 데이터 + 함수

3) 사용자 정의 타입

 

1. 변수 : 하나의 데이터를 저장할 수 있는 공간

2. 배열 : 같은 종류의 여러 데이터를 하나로 저장할 수 있는 공간

3. 구조체 : 서로 관련된 여러 데이터(종류 관계 없이)를 하나로 저장할 수 있는 공간

4. 클래스 : 데이터와 함수의 결합(구조체 + 함수)

 

 

사용자 정의 타입 : 원하는 타입(클래스)을 직접 만들 수 있다.

 

6 - 9, 10 (클래스의 정의) 까지!!

--------------------------------------

선언위치에 따른 변수의 종류

1. 클래스 영역 : iv , cv(static이 붙으면 cv이다)

2. 메서드 영역 : lv (지역변수)

 

class Varicables //{클래스 영역} -> 선언문만 가능
 { 
   int iv;          // 인스턴스 변수
   static int cv;   // 클래스 변수(static변수, 공유변수)
   
     void method()
     {
     	int lv = 0 ; // 지역변수{메서드 영역}  
        }
  
 }

 

 

변수의 생성 시기

  - cv(클래스변수) : 클래스가 메모리에 올라갈 때(클래스가 필요할 때 => 객체만들기 전에)

  - iv(인스턴스변수) : 인스턴스가 생성되었을 때(객체 생성했을때)

  - lv(지역변수) : 변수 선언문이 수행되었을 때

 

1. 인스턴스 변수(iv)

: 클래스 영역에 선언되며, 클래스의 인스턴스(객체)를 생성할 때 만들어진다.

  인스턴스는 독립적인 저장공간을 가지므로 서로 다른 값을 가질 수 있다.

 

2. 클래스 변수(cv)

: 클래스 변수를 선언하는 방법은 인스턴스 변수 앞에 static을 붙이기만 하면 된다.

  인스턴스마다 독립적인 저장공간을 갖는 인스턴스 변수와는 달리, 클래스변수는

  모든 인스턴스가 공통된 저장공간(변수)을 공유하게 된다. 

  한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야하는 속성의 경우 클래스 변수로 선언함.

  클래스가 메모리에 '로딩(loading)'될 때 생성되어 프로그램이 종료될때 까지 유지되며,

  앞에 public을 붙이면 같은 프로그램 내에서 어디서나 접근할 수 있는 전역변수의 성격을 갖는다.

 

3. 지역변수(lv)

:  메서드 내에 선언되어 메서드 내에서만 사용 가능하며, 메서드가 종료되면 소멸되어 사용할 수 없게 된다.

   for문 또는 while문의 블럭 내에 선언된 지역변수는, 지역변수가 선언된 블럭{ } 내에서만 사용 가능하며,

   블럭 { }을 벗어나면 소멸되어 사용할 수 없게 된다.

 

 

 

객체 = iv 여러개 묶어 놓은 것

 

클래스 변수와 인스턴스 변수

class Card {
    String kind;  // 무늬
    int number;   // 숫자
    
    static int width = 100;  // 폭
    static int height = 250; // 높이   
}

    Card c = new Card();     //객체 생성
		c.kind = "HEART";
		c.number = 5;
		Card.width = 200;    // c.width = 200;
		Card.height = 300;   // c.height = 300;

메서드

:  메서드는 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것이다.

   기본적으로 수학의 함수와 유사하며, 어떤 값을 입력하면 이 값으로 작업을 수행해서 결과를 반환한다.

  ※ 어떤 값(입력 )을 받아서 처리하고 그 결과를 반환(출력)

  ※ 메서드는 반드시 클래스 안에 있어야 한다.

 

메서드를 사용하는 이유

 1) 높은 재사용성

 2) 중복 코드의 제거 / 간결해서 이해하기 쉽다.

 3) 프로그램의 구조화

 

메서드의 장점과 작성지침

- 반복적인 코드를 줄이고 여러 문장을 메서드로 작성한다.

- 반복적으로 수행되는 여러 문장을 메서드로 작성한다.

- 하나의 메서드는 한가지의 기능만 수행하도록 작성하자

- 관련된 여러 문장을 메서드로 작성한다.

 

메서드 = 선언부 + 구현부

 

 

메서드의 호출

메서드의 이름(값1, 값2...) 

 

print99danAll();         // void print99danAll()메서드 호출
int result = add(3,5);   // int add(int x, int y)를 호출하고
                         // 결과를 result에 저장
                         
add( , ) // 괄호 안에 지정해준 값들 '인자(argument)' 또는 인수라고 하는데
         // 인자의 개수와 순서는 호출된 메서드에 선언된 매개변수(파라메터)와 일치해야 한다.

 

 

return 문

:  실행 중인 메서드를 종료하고 호출한 곳으로 되돌아간다.

 

1) 메서드가 정상적으로 종료되는 경우

  - 메서드의 블럭 { }의 끝에 도달했을 때

  - 메서드의 블럭 { }을 수행 도중 return 문을 만났을때

 

int multiply(int x, int y){
     int result = x * y;
     
     return result;   // 반환 타입이 void가 아니브로 return 꼭 써줘야 함.
    
  }
 
 int max (int a > b) {
      if( a > b )
      
     return a;    // 에러!! 조건식이 참일 때만 실행 함
 
  }
  
  
int max (int a > b) {
      if( a > b ) // 참일 때
         return a;
         
      else        // 거짓일 때
         return b;      
  }

 

호출 스택(call stack)

스택(stack) : 밑이 막힌 상자. 위에 차곡차곡 쌓인다.

 

 

메서드 수행에 필요한 메모리가 제공되는 공간

메서드가 호출되면 호출스택에 메모리 할당, 종료되면 해제 

아래에 있는 메서드가 위의 메서드를 호출함

맨위의 메서드 하나만 실행, 나머지는 대기중

 

6-22 호출 스택 까지

---------------------------------------------

 

기본형 매개변수

- 기본형 매개변수 : 변수의 값을 읽기만 할수있다. (read only) //기본형 8개 타입 // 변형안됨

- 참조형 매개변수 : 변수의 값을 읽고 변경할 수 있다. (read  & wirite)

 

static void change(int x){ // 여기서 int x는 기본형 매개변수
   x = 1000;               // 읽기만 할 수 있고 메소드 밖을 나가서 
                           // x를 변경시킬수 없다
                           // 변경시키고 싶으면 int x 를 참조형으로 바꿔야 함
   System.out.println("chang() : x =" + x);
}

 

 

참조형 매개변수

class Data2 { int x; }
------------------------------

class Ex6_7 {
   public static void main(String [] args) {
       Data2 d = new Data2 ();
       d.x = 10;
       System.out.println("main() : x =" + d.x);
       
       change(d)  // 참조변수 d
       System.out.println("After change(d)");
       System.out.println("main() : x = " + d.x);  // 
       // change(d)메서드에서 참조형인 Data d 의 주소를 복사했기 때문에
       // change(d)메서드 안에서 x의 값을 변경함 d.x = 1000;
  }

static void change(Data d){ // 매개변수(파라미터)로 참조형인 Data d를 넘겨준다.
   x = 1000;                // chang()가 매개변수의 주소를 복사한다
                            // x를 변경시킬수 있다!!
                            // change(); 메서드가 종료하고 호출했던 곳으로 돌아간다.
                          
   System.out.println("chang() : x =" + x);
  }
}

 

 

 

모든 참조형 타입의 값은 '객체의 주소'이다.

 

참조형 반환타입 : 메서드가 '객체의 주소'를 반환한다는 것

class Data3 { int x; }
------------------------------

class Ex6_8 {
   public static void main(String [] args) {
       Data3 d = new Data3 ();
       d.x = 10;
       System.out.println("main() : x =" + d.x);
       
       Data3 d2 = copy(d)  
       System.out.println("d.x = " + d.x);
       System.out.println("d2.x =  " + d2.x); 
       
  }

static Data3 copy(Data3 d){ // 매개변수(파라미터)로 참조형인 Data d를 넘겨준다.
  Data3 tmp = new Data3();  // 새로운 객체 tmp를 생성한다.
        
        tmp.x = d.x;  // d.x의 값을 tmp.x에 복사한다.                   
                          
        return tmp;   // 복사한 객체의 주소를 반환한다.
  }
}

 

 

static 객체 생성없이 호출 가능 / 참조변수 생략 가능

6_24,25 참조형매개변수, 참조형반환타입까지


스태틱 (static)메서드와 인스턴스 메서드

 

인스턴스 메서드

인스턴스 생성 후, '참조변수.메서드()' 이름으로 호출

인스턴스 멤버(iv, im)와 관련된 작업을 하는 메서드

메서드 내에서 인스턴스 변수(iv) 사용가능

 

 

스태틱매서드(클래스 메서드)

- 객체생성없이 '클래스 이름.메서드이름()'으로 호출가능

- 인스턴스멤버(iv,im)와 관련없는 작업을 하는 메서드

- 메서드 내에서 인스턴스 변수(iv) 사용불가

 

class MYMath2 {
	
	long a, b;
	
	long add() { //인스턴스 메서드
		return a + b;   // iv 사용
	}
	
	
	static long add(long a , long b) { //클래스 메서드(static)
		return a + b;   // iv 사용 안함
	}
	
}

 

public static void main(String[] args) {
	
System.out.println(MYMath2.add(200L,100L));  //클래스메서드 호출
		
MYMath2 mm = new MYMath2();  //객체생성(인스턴스 생성)
				
mm.a = 200L;
mm.b = 100L;
System.out.println(mm.add()); //인스턴스 메서드 호출
	
	}

 

 

Static은 언제 붙일까?

속성(멤버변수) 중에서 공통 속성에 static을 붙인다.

 

 

스태틱 메서드는 인스턴스 변수를 사용할 수 없다.

static void staticMerhod2(){  // 스태틱 메소드

  instanceMethod();   // <<= 인스턴스메소드 에러!!
  // 인스턴스 메서드로 iv로 작업하기 때문에 객체가 필요하다. iv가 필요하다.
  
}

 

static 메서드 =>  static 메서드 호출 가능?? => Yes

static 메서드 =>  인스턴스 변수 사용 가능?  => No (객체 생성해야 사용 가능)

static 메서드 =>  인스턴스 메서드 호출 가능? => No (iv를 작업하기 때문에)

static 메서드는 인스턴스 멤버를 쓸수 없나요?

=> static 메서드 호출시(항상 호출 가능) 객체(iv 묶음)가 없을 수도 있어서

 

오버로딩 

: 한 클래스 안에 같은 이름의 메서드 여러개 정의하는 것

 

오버로딩의 대표적인 예) println

 

오버로딩이 성립하기 위한 조건 3가지

1. 메서드 이름이 같아야 한다.

2. 매개변구의 개수 또는 타입이 달라야 한다

3. 반환 타입은 영향 없다.

 

※ 오버로딩의 올바른 예 - 매개변수는 다르지만 같은 의미의 기능 수행

 

 

6-32 생성자(constructor)

- 인스턴스가 생성될 때마다 호출되는 '인스턴스 초기화 메서드'

- 인스턴스 변수의 초기화 또는 인스턴스 생성시 수행할 작업에 사용

- 몇가지 조건을 제외하고는 메서드와 같다.

- 모든 클래스에는 반드시 하나 이상의 생성자가 있어야 한다.

 

※ 인스턴스 초기화 - 인스턴스 변수에 적절한 값을 저장하는 것.

 

 

Time t = new Time();
t.hout = 12;
t.minute = 34;
t.second = 56;

Time t = new Time(12, 34, 56);  // 생성자 호출
                                // 생성자가 하는 일 = 인스턴스 초기화

 

 

 

 

Card c = new Card();

 

1. 연산자 new에 의해서 메모리(heep)에 Card 클래스의 인스턴스(객체)가 생성된다.

2. 생성자 Card ()가 호출되어 수행된다.

3. 연산자 new의 결과로, 생성된 Card  인스턴스의 주소가 반환되어 참조변수 c에 저장된다.

 

생성자 = iv 초기화 메서드 

 

class Card () {

  // 매개변수 없는 생성자
  Card() {  
       // 생성자가 하는 일 : 인스턴스 초기화 작업
   }
            
  // 생성자 오버로딩          
  // 매개변수 있는 생성자
  Card(String kind, int number) {  
       // 생성자가 하는 일 : 인스턴스 초기화 작업 
   }
  
  
}

 

1. 이름이 클래스 이름과 같아야 한다.

2. 리턴값이 없다.(하지만 void는 붙이지 않는다.)

3. 모든 클래스는 반드시 1개 이상의  생성자를 가져야 한다. (없는경우 자바컴파일러 자동생성 됨)

 

기본생성자

- 매개변수가 없는 생성자

- 생성자가 하나도 없을 때만, 컴파일러가 자동 추가 해줌

 

클래스이름() { } // 기본생성자

Point() { } // Point 클래스의 기본생성자 

 

 

매개변수가 있는 생성자

 

 

 

생성자 this()

- 같은 클래스의 다른 생성자를 호출 할 때 사용

   다른 생성자 호출은 생성자의 첫 문장에서만 가능

class Car () {

  String color;
  String gearType;
  int door;
  
  Car() {
    color = "white";
    gearType = "auto";
    door = 4;
    }
 -----------------------------------------   
   Car() {
    this("white", "auto", 4);  // 같은 클래스 의 다른 생성자를 호출할 때 
    // 첫줄에서만 this를 쓰자. 첫줄이 아니면 에러남!
    
    }
    
  Car(String c, String g,int d) {
    color = c;
    gearType = g;
    door = d;
    }

 

참조변수 this

- 인스턴스 자신을 가리키는 참조변수. 인스턴스의 주소가 저장되어 있음

   모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재

- 인스턴스 메서드(생성자 포함)에서 사용가능

- 지역변수(lv)와 인스턴스변수(iv)를 구별할 때 사용

(this는 생략 가능 하다. iv와 lv가 이름이 같을때 구별하기 위해)

 

  Car(String color, String gearType, int door) {  // 지역변수 lv
    this.color    = color;
    this.gearType = gearType;
    this.door     = door;
    // iv         // lv
    // 참조변수.변수이름
    
    }

 

생성자를 이용한 인스턴스의 복사

- 인스턴스간의 차이는 인스턴스변수의 값 뿐 나머지는 동일하다.

- 생성자에서 참조변수를 매개변수로 받아서 인스턴스 변수들의 값을 복사한다.

- 똑같은 속성 값을 갖는 독립적인 인스턴스가 하나 더 만들어진다.

 

6-36. 37 생성자 this/ 참조변수 this 까지


 

6-38 변수의 초기화

- 변수를 선언하고  처음으로 값을 저장하는 것

- 멤버변수(인스턴스 변수 iv, 클래스변수 cv) 와 배열은

   각 타입의 기본값으로 자동초기화 되므로 초기화를 생략할수 있다.

- 지역변수는 사용전에 꼭 초기화 해줘야 한다.

 

 

 

 

 

 

 

 

class IntTest {
  int x;            // 인스턴스 변수 iv (자동 초기화)   // 값이 0으로 자동초기화
  int y = x;        // 인스턴스 변수
  
    void method (){
       int i;        // 지역변수 lv  // int i = 0; 으로 초기화 해줘야 함
       int j = i;    // 에러!!. 지역변수를 초기화 하지 않고 사용했기 때문
                     // 지역변수는 꼭 수동 초기화를 해야한다.
    
   }
}

 

 

멤버 변수(iv, cv)의 초기화

 1) 자동 초기화

 2) 간단 초기화 (대입연산자)

 3) 복잡한 초기화 ({블럭})

 

 

 

1. 명시적 초기화(=) 대입연산자  (쉬운 초기화)

class Car {

 	int door = 4; 		       // 기본형 변수의 초기화
    Engine e = new Engine();   // 참조형 변수의 초기화

참조형이 가지는 값은 NUILL 또는 객체의 주소 값  : 객체를 만들어서 넣어줘야 한다.

참조형에 NULL값 넣는건 초기화가 아니다.

 

2. 초기화 블럭 (복잡한 초기화) <= 여러 문장 넣기

  - iv 초기화 -> 인스턴스 초기화 블럭 : { }

  - cv 초기화 -> 클래스 초기화 블럭 : Static { }

 

3. 생성자 (iv 초기화, 복잡한 초기화)

 

class StaticBlockTest {
 
	static int[] arr = new int[10];  // 명시적 초기화(간단 초기화)
    
   //cv복잡 초기화
    static {  //클래스 초기화 블럭 - 배열 arr을 난수로 채운다.
       for(int i = 0; i < arr.length; i ++){
       		arr[i] = (int)(Math.random()*10)+1;
       }
    }
  }

 

멤버변수의 초기화 시기 순서 cv => iv   // 자동 - 간단 - 복잡 { }

클래스 변수 초기화 시점 : 클래스가 처음 메모리에 올라갈때 (로딩) 단 한번

인스턴스 변수 초기화 시점 : 인스턴스가 생성될 때 마다

변환함수
  - 자료의 형을 일시적으로 변환하기 위한 함수
  - TO_CHAR(숫자나 날짜를 문자로), 

    TO_NUMBER(문자나 날짜를 숫자로), 

    TO_DATE(문자를 날짜 데이터로 변환),

    CAST(바꾸고싶은대로 바꿈) 제공


 1. CAST(expr  AS 타입명) -- 기본형으로밖에 밖을수 없음
    . 'expr'형을 '타입명'으로 변환
    . 물리적으로 변환되지는 않음
    
    -- 변환하고자 하는 새로운 데이터 타입으로 출력
    
    

사용예) 2020년 6월 일자별 판매집계를 조회하시오.

SELECT CAST(SUBSTR(A.CART_NO,1,8) AS DATE) AS 일자,
 -- 날짜형식으로 바꿈(형변환)
       SUM(A.CART_QTY) AS 판매수량,
       SUM(A.CART_QTY*B.PROD_PRICE) AS 판매금액
  FROM CART A, PROD B
 WHERE A.CART_PROD=B.PROD_ID
 GROUP BY CAST(SUBSTR(A.CART_NO,1,8) AS DATE)
 ORDER BY 1;

 


 2. TO_CHAR(expr [, fmt])
   - 문자열(CHAR, CLOB -> VARCHAR2), 숫자, 날짜 타입의 데이터를 'fmt' 형식에 맞는 
     문자열 자료로 형변환 -- 특정한 경우 문자열을 문자열로 바꿀수 있다. 

     (예 -고정길이 문자열 -> 가변길이 문자열)
   - format 문자열은 날짜와 숫자로 구분

 

 

 

 

** 날짜 format string

더보기

-----------------------------------------------------------------------------------
    format                          기능                          예
-----------------------------------------------------------------------------------
    CC                               세기                    SELECT TO_CHAR(SYSDATE, 'CC') FROM DUAL;
    AD, BC                         서기                    SELECT TO_CHAR(SYSDATE, 'AD YYYY') FROM DUAL; 
    YYYY,YYY,YY,Y           년도                    SELECT TO_CHAR(SYSDATE, 'YYYY'),
                                                                                   TO_CHAR(SYSDATE, 'YYY'),
                                                                                   TO_CHAR(SYSDATE, 'YY'),
                                                                                   TO_CHAR(SYSDATE, 'Y') FROM  DUAL;


    Q                                 분기                   SELECT TO_CHAR(SYSDATE, 'YYYY/MM Q') FROM DUAL;

                                                                  -- 2022/11/4분기
    MM, RM                       월                      SELECT TO_CHAR(SYSDATE, 'MM'),
                                                                                 TO_CHAR(SYSDATE, 'RM'),
                                                                                 TO_CHAR(SYSDATE, 'MONTH'),
                                                                                 TO_CHAR(SYSDATE, 'MON') FROM DUAL;  
    MONTH, MON         '월'문자열 

                                     추가 출력     
    WW,                         년의 주수, 

      W                           월의 주수              SELECT TO_CHAR(SYSDATE, 'WW'),
                                                                 TO_CHAR(SYSDATE, 'W')  FROM DUAL;  
    DDD,DD,D           년의 일,월의 일,

                                 주의 일                    SELECT TO_CHAR(SYSDATE, 'DDD'),   
                                                                                TO_CHAR(SYSDATE, 'DD'),   
                                                                                TO_CHAR(SYSDATE, 'D'),  
                                                                                TO_CHAR(SYSDATE, 'DAY'),
                                                                                TO_CHAR(SYSDATE, 'DY') FROM DUAL;    
                                                     
    DAY,DY             요일  -- 수요일 / 수(약자)
    AM, PM, A.M        오전, 오후              SELECT TO_CHAR(SYSDATE, 'AM'),
                                                                              TO_CHAR(SYSDATE, 'P.M.')  FROM DUAL; 
                                                     
    P.M.               --  SYSDATE를 받으면 아무리 P.M.을 선언해도 오전이면 오전이라고 표기된다.
    HH,HH12,HH24       시간
    MI                             분
    SS,SSSSS               초                     SELECT TO_CHAR(SYSDATE, 'HH:MI:SS'),
                                                                            TO_CHAR(SYSDATE, 'HH12:MI:SSSSS'),  
                                                                            TO_CHAR(SYSDATE, 'HH24:MI:SS')  
                                                                            FROM DUAL;




    "사용자정의 문자열"         

    SELECT TO_CHAR(SYSDATE, 'YYYY"년" MM"월" DD"일"') FROM DUAL;                                                                 
    >> 2022년 11월 23일


-- **    
--  AD, BC 원본데이터가 이미 저장되어있어서 둘다 '서기'로 표시됨
--  RM 로마자로 월 표기
--  MONTH(월의 풀네임), MON(월의 약자 - JUN,DEC) /한글은 월을 표현하는 약자가 없어서 같은 형식으로 출력됨
--  1년 52주/WW 오늘이1년의 몇 주 차인지/ W 이번달에 오늘은 몇주차인지
--  (11월 23일 WW : 오늘은 1년의 47주차/W : 11월의 4주차)
--   DDD : 날짜가 3자리로 표현한다. => 1월 1일부터 오늘까지 경과된 일 
--   DD : 2자리로 표현 이번달 1일부터 오늘까지 경과된 일,
--   D  : 이번주의 월요일부터 오늘까지 경과된 일  
--  HH = HH12 : 12시간 형식,HH24 : 24시간 형식
--  SS : 1분은 60초 / SSSSS : 5자리로 표기함 : 오늘 0시0초부터 시작해서 지금까지 경과된 초를 출력

 

 

 


** 숫자 format string

사용예) -- 결과는 숫자가 아닌 문자열!!
SELECT TO_CHAR(12345,'999,999'),     --  12,345     /나인모드
       TO_CHAR(12345,'000,000'),     --  012,345
       TO_CHAR(12345,'999,999.99'),  --  12,345.00  /나인모드여도 소숫점0출력
       TO_CHAR(12345,'999,999.00'),  --  12,345.00
       TO_CHAR(-12345,'999,999MI'),  --  12,345-    / 음수부호가 오른쪽에 표기
       TO_CHAR(-12345,'999,999PR'),  --  <12,345>   / 음수인경우 < 숫자 > 표기 / 양수인경우 일반숫자 표기
       TO_CHAR(12345,'L999,999'),    --  ₩12,345   / Location의 'L'
       TO_CHAR(12345,'$000,999')     --  $012,345   / 달러표기와 제로모드
 FROM DUAL

 

더보기

-----------------------------------------------------------------------------------
    format                                        기능                              
-----------------------------------------------------------------------------------
    9                                        유효숫자출력, 무효의                       
                                              0은 공백 처리
    0                                        유효숫자출력, 무효의 
                                              0은 '0' 출력
    $,L                                     화폐기호 출력 -- 맨왼쪽에 출력
    MI                                     음수인 경우 우측에 '-'출력--( 1234-)
    PR                                    음수인 경우 우측에 < >안에 출력
    ,(Comma)                         3자리마다 자리점 출력
    .(DOT)                              소숫점 출력

 

 


/* 나인모드         제로모드            
** 01234.30        01234.30
   99,999.99       00,000.00
-------------------------------- 유효숫자 출력
   1,234           01,234.30
   0공백처리         0 출력
(소숫점은 0출력)

 화폐 기호 : $ 1,234   / L 1,234 L: 다른나라 화폐기호 */
 


  

   SELECT TO_CHAR('345') + 9999  -- 실행됨 : 10344
     FROM DUAL; 
      
   SELECT TO_CHAR('1,344') + 9999  -- 실행불가 : 1,344 => 콤마 때문에 
     FROM DUAL;

 

 

사용예) 

    SELECT TO_DATE('20211230'), -- 숫자가 날짜로 바뀜
           TO_DATE(20211230),   -- 숫자가 날짜로 바뀜
           TO_DATE('20211230','YYYY-MM-DD'),  -- 'YYYY-MM-DD' 여도 == 2021/12/30 표기
           TO_CHAR(TO_DATE('20211230095023','YYYYMMDDHH24MISS'),'YYYY-MM-DD HH24:MI:SS')
           -- 날짜타입으로 변경 => TO_CHAR로 YYYY-MM-DD 형식으로 표기
      FROM DUAL;


           
사용예)'2022.08.25'를 날짜형식으로 변환하고 10일 후의 날짜와 해당월의 마지막 날짜를 구하시오

    SELECT TO_DATE('2022.08.25','YYYY/MM/DD'),          -- 2022/08/25
           TO_DATE('2022.08.25','YYYY/MM/DD') + 10,     -- 2022/09/04
           LAST_DAY(TO_DATE('2022.08.25','YYYY/MM/DD')) -- 2022/08/31
      FROM DUAL;
           
    
    SELECT TO_DATE('2022년 08월 25일','YYYY/MM/DD'),  -- 에러남
           TO_DATE('2022 08 25','YYYY/MM/DD') + 10,     -- 2022/09/04
           LAST_DAY(TO_DATE('2022.08.25','YYYY/MM/DD')) -- 2022/08/31
      FROM DUAL; 
      
  
    --  출력되기 위해서     형식지정문자열을 기술해줘야함
    SELECT TO_DATE('2022년 08월 25일','YYYY"년" MM"월" DD"일"') + 5, -- 2022/08/30
           TO_DATE('2022 08 25','YYYY/MM/DD') + 10,                 -- 2022/09/04
           LAST_DAY(TO_DATE('2022.08.25','YYYY/MM/DD'))             -- 2022/08/31
      FROM DUAL;

    
 4. TO_NUMBER(expr [, fmt])
   - 문자열 데이터 expr을 숫자 타입으로 형을 변환 시킴
   - 'expr'은 반드시 숫자로 변환 가능해야하며 숫자로 변환할 수 없는 문자열이 포함된 경우
     'expr'이 출력되기 위해 요구되는 형식지정문자열을 기술해야 함.
   - 'fmt'은 TO_CHAR에 사용된 숫자 format string과 같다.
   

 

   
사용예)

    SELECT TO_NUMBER('12345'),
           TO_NUMBER('1234.08') FROM DUAL; 
    -- 소숫점은 별도의 형식없이 그냥 숫자로 변환됨
    
           
    SELECT TO_NUMBER('12,345'),   -- 콤마 사용으로 에러남
                   TO_NUMBER('12,345.08') FROM DUAL;       

    SELECT TO_NUMBER('12,345','99,999'),    
           TO_NUMBER('12,345.08','99,999.99') FROM DUAL;  
     -- 콤마를 사용하려면 '99,999'의 사용자지정형식 사용       
     -- 기본숫자열 '12345' 로 표기됨  
           

    SELECT TO_NUMBER('<12,345>','99,999PR'),   -- 음수 '-12,345'
           TO_NUMBER('₩12,345.08', 'L99,999.00') FROM DUAL;   
            -- 원본숫자 '12345.08' 로 표기됨

 

 등위함수(WINDOW 분석함수)
  - 특정 컬럼을 기준으로 순위를 부여할때 사용
  - RANK, DENSE_RANK, ROW_NUMBER 함수 제공
  - SELECT 절에 사용

 


(사용형식)
    RANK()|DENSE_RANK()|ROW_NUMBER() 

             OVER(ORDER BY 컬럼명1[ASC|DESC][, 컬럼명2 [ASC|DESC],...])
    . RANK() : '컬럼명1'의 값이 같으면 같은 순위 부여하고 동점순위가 n개일 때

                      차 순위는 '현재순위' + 'n'임
        ex) 18,16,16,16,14,13,10
                  1  2  2  2  5  6  7
    . DENSE_RANK() : '컬럼명1'의 값이 같으면 같은 순위 부여하고 동점순위가 n개일 때

                                     차 순위 차례대로 다음값 부여
           ex) 18,16,16,16,14,13,10
                  1  2  2  2  3  4  5
    . ROW_NUMBER :  '컬럼명1'의 값이 같아도 차례대로 순위부여 
      ex) 18,16,16,16,14,13,10
                  1  2  3  4  5  6  7 -- 마지막 번호는 전체 데이터의 갯수

사용예) 회원테이블에서 회원들의 마일리지 순으로 등수를 부여하시오. 같은 값이면 동일 등수를 부여하고
        차순위는 동점자 수만큼 건너뛴 등수부여
        Alias는 회원번호,회원명,나이,마일리지,등수

    SELECT MEM_ID AS 회원번호,
           MEM_NAME AS 회원명,
           EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM MEM_BIR) AS 나이,
           MEM_MILEAGE AS 마일리지,
           RANK() OVER(ORDER BY MEM_MILEAGE DESC) AS "등수1(RANK)", 
           DENSE_RANK()  OVER(ORDER BY MEM_MILEAGE DESC) AS "등수2(DENSE_RANK)", 
           ROW_NUMBER() OVER(ORDER BY MEM_MILEAGE DESC)AS "등수3(ROW_NUMBER)"
      FROM MEMBER

 

 

 

사용예) 회원테이블에서 회원들의 마일리지 순으로 등수를 부여하시오. 
       마일리지가 동일한 값이면 나이가 적은 회원에게 앞선 등수를 부여하고
       나이도 같은 값이면 동일 등수를 부여하고 차순위는 동점자 수만큼 건너뛴 등수를 부여하세요
       Alias는 회원번호,회원명,나이,마일리지,등수
        
   

SELECT MEM_ID AS 회원번호,
       MEM_NAME AS 회원명,
       EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM MEM_BIR) AS 나이,
       MEM_MILEAGE AS 마일리지,
       RANK() OVER (ORDER BY MEM_MILEAGE DESC,
                             EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM MEM_BIR) ASC) 
                             AS "등수1(RANK)", 
       DENSE_RANK() OVER(ORDER BY MEM_MILEAGE DESC,
                                  EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM MEM_BIR) ASC)
                                 AS "등수2(DENSE_RANK)", 
       ROW_NUMBER() OVER(ORDER BY MEM_MILEAGE DESC,
                                  EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM MEM_BIR) ASC) 
                                 AS "등수3(ROW_NUMBER)"        
  FROM MEMBER

 

** 그룹내 순위부여
  - 그룹별로 순위 부여


(사용형식)
    RANK()|DENSE_RANK()|ROW_NUMBER() OVER(PARTITION BY 컬럼명1[컬럼명2,...]  
                                          ORDER BY 컬럼명1[ASC|DESC][,컬럼명2 [ASC|DESC], ...]

-- PARTITION BY 그룹을 묶는 것 GROUP BY과 같음

 

사용예) 사원테이블에서 각 부서별로 급여순으로 순위를 부여하시오(RANK()함수 사용)
        Alias는 사원번호,사원명,부서코드,급여,순위

 SELECT EMPLOYEE_ID AS 사원번호,
        EMP_NAME AS 사원명,
        DEPARTMENT_ID AS 부서코드,
        SALARY AS 급여,
        RANK() OVER(PARTITION BY DEPARTMENT_ID 
                    ORDER BY SALARY DESC) AS 순위
   FROM HR.EMPLOYEES
  ORDER BY 3;

 

 

 

 

 

 

사용예)2020년 분류별 판매액집계를 구하고 분류별 순위를 조회하시오
     Alias는 분류코드,분류명,판매액,순위

(서브쿼리) 
    SELECT B.LPROD_GU AS 분류코드,
           B.LPROD_NM AS 분류명,
           SUM(A.CART_QTY*C.PROD_PRICE) AS 판매액    
      FROM CART A, LPROD B, PROD C
     WHERE A.CART_PROD=C.PROD_ID
       AND C.PROD_LGU=B.LPROD_GU
       AND A.CART_NO LIKE '2020%'
     GROUP BY B.LPROD_GU ,B.LPROD_NM
     ORDER BY 1;


 --------------------------------------------------------------  

 SELECT D.BLGU AS 분류코드,
        D.BLNM AS 분류명,
        TO_CHAR(D.CSUM,'999,999,999') AS 판매액,
        RANK() OVER( ORDER BY D.CSUM DESC) AS 순위
   FROM (SELECT B.LPROD_GU AS BLGU,
                B.LPROD_NM AS BLNM,
                SUM(A.CART_QTY*C.PROD_PRICE) AS CSUM     
           FROM CART A, LPROD B, PROD C
          WHERE A.CART_PROD=C.PROD_ID
            AND C.PROD_LGU=B.LPROD_GU
            AND A.CART_NO LIKE '2020%'
          GROUP BY B.LPROD_GU ,B.LPROD_NM)D


-----------------------------------------------------------------------------                      

(제품별집계 후 분류별 순위)

SELECT B.LPROD_GU AS 분류코드,
       B.LPROD_NM AS 분류명,
       P.PROD_ID AS 상품코드,
       P.PROD_NAME AS 상품명,
       TO_CHAR(D.CSUM,'999,999,999') AS 판매액,
       RANK() OVER(PARTITION BY B.LPROD_GU ORDER BY D.CSUM DESC) AS 순위 
       --그룹별로 순위
  FROM LPROD B, PROD P,
       (SELECT A.CART_PROD AS ACID,                   
               SUM(A.CART_QTY*C.PROD_PRICE) AS CSUM     
          FROM CART A, PROD C
         WHERE A.CART_PROD=C.PROD_ID
         GROUP BY A.CART_PROD)D        
 WHERE B.LPROD_GU=P.PROD_LGU
   AND P.PROD_ID=D.ACID
 ORDER BY 1;

 

ROLLUP 과 CUBE
  - 다양한 집계를 반환
  - 반드시 GROUP BY 절에서만 사용되어야 함


  1) ROLLUP(col1[, col2,.. coln])
    . 부분합계와 전체합계를 반환
    . ROLLUP 절에 기술된 컬럼들을 이용하요 레벨별 합계를 반환
    . 레벨은 모든 컬럼이 적용된 합계가 가장 하위레벨이고, 그 이후 부터 오른쪽 부터 컬럼을 하나씩 
      제가한 단계(레벨)별 합계반환을 하며, 마지막으로 전체합계를 반화
    . ROLLUP 절에 사용된 컬럼의 수가 n개 일때 n+1개의 합계 반환

사용예)계정_SAMPLE 계정의 KOR_LOAN_STATUS 테이블에서 기간별, 지역별, 구분별 대출합계를 조회하시오
(ROLLUP을 사용하지 않은 경우)

    SELECT PERIOD AS 기간,
           REGION AS 지역,
           GUBUN AS 구분,
           SUM(LOAN_JAN_AMT) AS 대출합계 -- 기간별로 그룹을 묶고, 기간이 같은 같은 지역별로 묶고
        FROM LHY93_SAMPLE.KOR_LOAN_STATUS
    GROUP BY PERIOD,REGION,GUBUN -- 기간>>지역>>구분 이라는 그룹으로 적용되어진 합계가 나옴
    ORDER BY 1;


-- LOAN_JAN_AMT(NUMBER) : 대출잔액

 


(ROLLUP을 사용하는 경우)

  SELECT PERIOD AS 기간,
         REGION AS 지역,
         GUBUN AS 구분,
         SUM(LOAN_JAN_AMT) AS 대출합계 -- 기간별로 그룹을 묶고, 기간이 같은 같은 지역별로 묶고
    FROM LHY93_SAMPLE.KOR_LOAN_STATUS
   GROUP BY ROLLUP(PERIOD,REGION,GUBUN) -- ROLLUP 3개가 다 적용되어진 합계
   ORDER BY 1;


    -- 컬럼의 갯수가 3개 => 맨마지막에 전체합계

  -- 전체합계
      SELECT SUM(LOAN_JAN_AMT) AS 대출합계
        FROM LHY93_SAMPLE.KOR_LOAN_STATUS;

 

** 부분 ROLLUP
  - GROUP BY 절에 사용되는 컬럼 중 일부만 ROLLUP절에 사용된 경우

    SELECT PERIOD AS 기간,
           REGION AS 지역,
           GUBUN AS 구분,
           SUM(LOAN_JAN_AMT) AS 대출합계 
      FROM LHY93_SAMPLE.KOR_LOAN_STATUS
     GROUP BY PERIOD, ROLLUP(REGION,GUBUN)
     ORDER BY 1;
   -- PERIOD 고정된 상수형태로 놓는다. 전체합계는 나오지 않는다.

 

 2) CUBE(col1[, col2,.. coln])
   . CUBE절에 사용된 컬럼들의 조합 가능한 모든 경우의 집계를 반환
   . CUBE절에 사용된 컬럼의 수가 n개일 때 집계의 종류는 2^n가지임 
   -- 결과의 종류가 너무 다양해서 특수한 상황 아니면 ROLLUP을 쓴다.
   
(CUBE를 사용하는 경우)

    SELECT PERIOD AS 기간,
           REGION AS 지역,
           GUBUN AS 구분,
           SUM(LOAN_JAN_AMT) AS 대출합계 
      FROM LHY93_SAMPLE.KOR_LOAN_STATUS
     GROUP BY CUBE(PERIOD,REGION,GUBUN)  --432의 결과
     ORDER BY 1;


   

 

 

 

 

집계함수
 - 자료를 특정 컬럼을 기준으로 그룹으로 분리하여 각 그룹별 합계, 평균 등을 구하여 반환
 - 결과가 다중행으로 반환
 - SUM , AVG, COUNT, MAX, MIN 등 제공
 - 집계함수는 집계함수를 포함할 수 없다.-- 집계함수는 일반함수를 포함할 수 있다.
 
(사용형식)
    SELECT [컬럼 list],
집계함수 --집계함수만 사용되어질수 있다. -> 그룹바이 안 쓸수가 있다.
        FROM 테이블명 
      [WHERE 조건]
      [GROUP BY 컬럼명[, 컬럼명, ...]] 
      [HAVING 조건]
      [ORDER BY 컬럼|컬럼인덱스 [ASC|DESC], ...]
      - SELECT 절에서 집계함수 이외의 컬럼이 사용되면 반드시 GROUP BY 절이 기술되어야 함
      - GROUP BY 절에는 SELECT 절에 기술된 모든 일반 컬럼이 기술되어야 함
      - GROUP BY 절에 기술된 컬럼은 왼쪽에 기술된 컬럼부터 대분류, 중분류.. 등으로 그룹화되어짐
      - 집계함수에 조건이 부여될때는 HAVING 절을 이용해야 함

 

-- SELECT 절 컬럼리스트에 없어도 필요하다면 그룹바이 절에서 기준으로 사용될 수 있다.

-- 첫번째컬럼을 기준으로 그룹을 묶고, 그 다음 컬럼을 대그룹 안의 중분류로..


      
1. SUM(expr), AVG(expr), MAX(expr), MIN(expr), COUNT(*|col)
  - SUM : 각 그룹으로 기술된 expr의 모든 값의 합을 반환
  - AVG : 각 그룹으로 기술된 expr의 평균 값을 반환 -- 소숫점이 나와서 ROUND나 TRUNC로 잘라줘야함
  - MAX : 각 그룹으로 기술된 expr의 최대 값을 반환 -- 행의 최대값 GREATEST / 열의 최대값 MAX
  - MIN : 각 그룹으로 기술된 expr의 최소 값을 반환
  - COUNT : 각 그룹에 포함된 행의 수를 반환 -- 자료의 수를 구할때 쓰임
    . '*'를 사용하면 NULL 값도 하나의 행으로 카운팅됨.(일반적인 행의수, 자료수를 반환할때 사용)
    -- null 값이든 아니든 모두 카운팅 하고싶을때 *
    . 'col' : 해당 컬럼의 값 중 NULL이 아닌 행의 갯수 반환(보통 외부 조인시 사용)

 

사용예) 사원테이블에서 전체 사원의 수, 사원의 평균임금을, 임금의 합계를 조회하시오. 

             --그룹이 전체 테이블이여야 함. 일반컬럼이 셀렉트절에 없어야함.
     

  SELECT COUNT(*) AS "전체사원 수", 
         ROUND(AVG(SALARY)) AS 평균임금, 
         SUM(SALARY) AS 급여합계,
         ROUND(SUM(SALARY)/ COUNT(*))
    FROM HR.EMPLOYEES;

 

 

 

 

사용예) 사원테이블에서 부서별 사원의 수를 조회하시오.

SELECT DEPARTMENT_ID AS 부서코드, -- ~별 : 일반컬럼
       COUNT(*) AS "사원의 수"
  FROM HR.EMPLOYEES
 GROUP BY DEPARTMENT_ID -- 일반컬럼 기술(집계함수가 포함되면 그대로)
 ORDER BY 1;

 

 

 

 

 

 

 

 

 

사용예) 사원테이블에서 부서별 평균급여를 조회하시오.

SELECT DEPARTMENT_ID AS 부서코드, 
       COUNT(*) AS "사원의 수",
       ROUND(AVG(SALARY)) AS 평균급여
  FROM HR.EMPLOYEES
 GROUP BY DEPARTMENT_ID 
 ORDER BY 1;


 

 

 

 

사용예) 사원테이블에서 부서별 사원의 수가 5명 이상인 부서를 조회하시오.   

SELECT DEPARTMENT_ID AS 부서코드, 
       COUNT(*) AS "사원의 수",
       ROUND(AVG(SALARY)) AS 평균급여
  FROM HR.EMPLOYEES
--   에러 :   WHERE COUNT(*)>= 5 
--   그룹함수가 이곳에는 기술될수 없습니다.
 GROUP BY DEPARTMENT_ID 
HAVING COUNT(*)>= 5  --  GROUP BY 다음에 기술되어야 한다.
 ORDER BY 1;

 

 SELECT A.DID AS 부서코드,
        A.CNT AS 인원수
   FROM (SELECT DEPARTMENT_ID AS DID,     
                COUNT(*) AS CNT         
           FROM HR.EMPLOYEES -- VEIW 는 가상의 테이블이다.
          GROUP BY DEPARTMENT_ID       
          ORDER BY 2 DESC)A -- A를 하나의 테이블로 => A.DID / A.CNT       
  WHERE ROWNUM=1; 
  -- 제일 첫번째 행(오라클에서 제공하는 컬럼 = Psudo 컬럼 = 가상의 컬럼)

 

  

 

 

 SELECT  MAX(A.CNT) AS 인원수           
   FROM  (SELECT DEPARTMENT_ID AS DID,     
                 COUNT(*) AS CNT          
            FROM HR.EMPLOYEES 
           GROUP BY DEPARTMENT_ID       
           ORDER BY 2 DESC)A; 

 SELECT  A.DID,
         MAX(A.CNT) AS 인원수
   FROM  (SELECT DEPARTMENT_ID AS DID,     
                 COUNT(*) AS CNT             
            FROM HR.EMPLOYEES 
           GROUP BY DEPARTMENT_ID       
           ORDER BY 2 DESC)A 
  GROUP BY A.DID; 
  -- 그룹 12개 생성, 각 그룹별 인원수 최대값 MAX

 


사용예) 상품테이블에서 분류별 상품의 수를 조회하시오.

   SELECT PROD_LGU AS 분류코드,
          COUNT(*) AS "상품의 수"
     FROM PROD
    GROUP BY PROD_LGU
    ORDER BY 1;

 

 

 

 

 

 

사용예) 매입테이블에서 2020년 상반기 월별 매입집계를 조회하시오.

    SELECT EXTRACT(MONTH FROM BUY_DATE) AS 월, 
           SUM(BUY_QTY) AS 매입수량합계, 
           SUM(BUY_QTY*BUY_COST) AS 매입금액합계
      FROM BUYPROD
     WHERE BUY_DATE BETWEEN TO_DATE('20200101') 
       AND TO_DATE('20200630')
     GROUP BY EXTRACT(MONTH FROM BUY_DATE)
     ORDER BY 1;

 

사용예) 매입테이블에서 2020년 상반기 매입금액 합계가 500만원을 넘는 제품을 조회하시오.

    SELECT BUY_PROD AS 제품별,
           SUM(BUY_QTY) AS 매입수량합계, 
           SUM(BUY_QTY*BUY_COST) AS 매입금액합계
      FROM BUYPROD
     WHERE BUY_DATE BETWEEN TO_DATE('20200101') 
       AND TO_DATE('20200630')
     GROUP BY BUY_PROD
    HAVING SUM(BUY_QTY*BUY_COST)>= 5000000
     ORDER BY 1;

 

사용예) 회원테이블에서 회원들의 성별 평균 마일리지를 조회하시오.

SELECT CASE WHEN SUBSTR(MEM_REGNO2,1,1) IN('1','3') THEN 
                     '남성회원'
                ELSE 
                     '여성회원'
                END AS 구분,                 
                ROUND(AVG(MEM_MILEAGE)) AS 평균마일리지    
  FROM MEMBER
 GROUP BY CASE WHEN SUBSTR(MEM_REGNO2,1,1) IN('1','3') THEN  
                    '남성회원'
                ELSE 
                    '여성회원'
                END;-- 별칭 전까지 복붙

 

 

사용예) 2020년 5월  100만원 이상 구매한 회원의 회원번호, 회원명, 나이, 직업, 마일리지, 구매금액 합계를 조회하시오.
-- 회원별 구매금액 합계

(메인쿼리)
    SELECT A.CART_MEMBER AS 회원번호,     
           EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM MEM_BIR) AS 나이, 
           B.MEM_JOB AS 직업, 
           B.MEM_MILEAGE AS 마일리지,
      FROM
(서브쿼리 : 2020년 5월 회원별 구매금액 합계가 1000만원 이상인 회원)  
  SELECT A.CART_MEMBER AS MID, 
         SUM(A.CART_QTY*C.PROD_PRICE) AS PSUM
    FROM CART A, PROD C
   WHERE A.CART_PROD=C.PROD_ID
     AND A.CART_NO LIKE '202005%'
   GROUP BY A.CART_MEMBER
  HAVING SUM(A.CART_QTY*C.PROD_PRICE)>10000000

 

 SELECT P.MID AS 회원번호, 
        B.MEM_NAME AS 회원명, 
        EXTRACT(YEAR FROM SYSDATE) 
        - EXTRACT(YEAR FROM B.MEM_BIR) AS 나이, 
        B.MEM_JOB AS 직업, 
        B.MEM_MILEAGE AS 마일리지, 
        P.PSUM AS "구매금액 합계"
   FROM MEMBER B,
        (SELECT A.CART_MEMBER AS MID, 
                SUM(A.CART_QTY*C.PROD_PRICE) AS PSUM
                FROM CART A, PROD C
          WHERE A.CART_PROD=C.PROD_ID
            AND A.CART_NO LIKE '202005%'
          GROUP BY A.CART_MEMBER
         HAVING SUM(A.CART_QTY*C.PROD_PRICE)>10000000)P
  WHERE B.MEM_ID=P.MID;

 

 

사용예) 2020년 4월 제품별 매출집계를 조회하시오.

 SELECT A.CART_PROD AS 제품코드, 
        B.PROD_NAME AS 제품명, 
        SUM(A.CART_QTY) AS 매출수량, 
        SUM(A.CART_QTY*B.PROD_PRICE) AS 매출금액
   FROM CART A, PROD B
  WHERE A.CART_PROD=B.PROD_ID
    AND A.CART_NO LIKE '202004%'
  GROUP BY A.CART_PROD, B.PROD_NAME 
  ORDER BY 1;
  --  GROUP BY은 SELECT절의 집계함수 
  --  빼고 일반 컬럼은 전부 기술한다.

 

 

사용예) 회원테이블에서 년령대별 평균마일리지를 조회하시오.

SELECT TRUNC(EXTRACT(YEAR FROM SYSDATE)
             - EXTRACT(YEAR FROM MEM_BIR),-1) AS 년령대, 
       ROUND(AVG(MEM_MILEAGE)) AS 평균마일리지
  FROM MEMBER
 GROUP BY TRUNC(EXTRACT(YEAR FROM SYSDATE) 
                - EXTRACT(YEAR FROM MEM_BIR),-1)
 ORDER BY 1;

    

 

 

사용예)(2020년 FROM 절 :회원별 구매수량합계)를 구하고 상위 5명의 결과를 출력하시오

(서브쿼리 : 2020년 회원별 구매수량합계)
   SELECT CART_MEMBER AS 회원번호,   
          SUM(CART_QTY) AS CSUM 
     FROM CART
    WHERE SUBSTR(CART_NO,1,4)='2020'
    GROUP BY CART_MEMBER
    ORDER BY 2 DESC
    
 -- 별칭 메인쿼리와 똑같으면 오류
(메인쿼리 : 상위 5명의 결과를 출력)
   SELECT 회원번호,회원명,구매수량합계
     FROM MEMBER A, 
          (서브쿼리) B
    WHERE A.MEM_ID=B.회원번호
      AND ROWNUM<5;

 

 (결합 : 상위 5명의 결과를 출력)
   SELECT B.CART_MEMBER AS 회원번호,
          A.MEM_NAME AS 회원명,
          B.CSUM AS 구매수량합계
     FROM MEMBER A, 
          (SELECT CART_MEMBER,
                  SUM(CART_QTY) AS CSUM 
            FROM CART
           WHERE SUBSTR(CART_NO,1,4)='2020'
           GROUP BY CART_MEMBER
           ORDER BY 2 DESC) B
    WHERE A.MEM_ID=B.CART_MEMBER
      AND ROWNUM<=5;

 

 

+ Recent posts