42일차 서브쿼리 / 컬렉션 프레임 웤ㅋ

쿠우·2022년 5월 25일
0

DB

복수 행 Sub-query - 스칼라가 아닌

가. 하나 이상의 행을 반환
나. 메인쿼리에서 사용가능한 연산자는 아래와 같음:
     (1) IN : 메인쿼리와 서브쿼리가 IN 연산자로 비교수행. 
              서브쿼리 결과값이 복수 개인 경우에 사용.
     (2) ANY : 서브쿼리에서, > 또는 < 같은 비교 연산자를 사용하고자 
               할 때 사용. 검색조건이 하나라도 일치하면 참.
     (3) ALL : 서브쿼리에서 > 또는 < 같은, 비교 연산자를 사용하고자
               할 때 사용. 검색조건의 모든 값이 일치하면 참.
     (4) EXISTS : 서브쿼리의 반환값이 존재하면, 메인쿼리를 실행하고,
                 반환값이 없으면 메인쿼리를 실행하지 않음.

-(1) IN 연산자 사용한 복수행 서브쿼리

-IN 메인쿼리와 동등비교연산자(=) 방식으로 복수개 비교할 때

-- 'Whalen' or 'Fay'와 동일한 월급여를 받는 사원조회

SELECT
    last_name,
    salary
FROM
    employees
WHERE
    -- 메인쿼리: 복수행 서브쿼리가 사용되었으므로, 
    -- 복수 값과 연산가능한 연산자 사용가능 (IN)
    -- salary IN ( 1000, 2000 )
    salary IN (
    -- 복수행에 단일행 연산자 사용한 경우:
    --  ORA-01427: single-row subquery returns more than one row
    -- salary = (

        -- 복수 행 비상관 서브쿼리: 'Whalen' 와 'Fay' 월급여 반환
        -- 메인쿼리로 결과값 전달
        SELECT salary
        FROM employees
        WHERE last_name IN ('Whalen', 'Fay')
    );

-- 월급여를 13000 보다 많이 받는 부서에 속한 모든 사원 조회

SELECT
    last_name,
    department_id,
    salary
FROM
    employees
WHERE
    -- 메인쿼리: 복수행 서브쿼리가 사용되었으므로, 
    -- 복수 값과 연산가능한 연산자 사용가능 (IN)
    -- department_id IN ( 100, 200 )
    department_id IN (
        -- 복수 행 비상관 서브쿼리: 월급여 > 13000인 사원목록 반환
        -- 메인쿼리로 결과값 전달
        SELECT
            department_id
        FROM
            employees
        WHERE
            salary > 13000

    );

(2) ALL 연산자 사용한 복수행 서브쿼리

-서브쿼리가 반환한 값 중 모든 값이 만족하게 반환
-ALL 모든 데이터를 최소값보다 작거나 최대값보다 큼을 만족 할 때 반환

 가. 서브쿼리 반환값이 복수 개.
 나. 메인쿼리에서, < or > 같은 비교연산자 사용하고자 할 때 사용.
 다. 메인쿼리의 비교연산자는 단일 행 연산자이기 때문에,
     메인쿼리의 복수행 연산자에 ALL 키워드 없이 사용하면 오류발생.
 라. ALL 연산자:
     서브쿼리에서 반환된 전체 행들에 대해서, 조건이 모두(all)
     만족해야 된다는 것을 의미.
 마. 구분:
     (1) > ALL (서브쿼리)
         - 서브쿼리에서 반환된 모든 데이터보다 큰 데이터 조회
         - 결국, 서브쿼리에서 반환된 모든 데이터 중,
           *최대값보다 큰* 데이터 조회

     (2) < ALL (서브쿼리)
         - 서브쿼리에서 반환된 모든 데이터보다 작은 데이터 조회
         - 결국, 서브쿼리에서 반환된 모든 데이터 중, 
           *최소값보다 작은* 데이터 조회

-- 직책이 IT_PROG인 사원 월급 조회

SELECT
    salary
FROM
    employees
WHERE
    job_id = 'IT_PROG'
ORDER BY
    1 ASC;

-- 직책이 IT_PROG인 사원의 월급보다 작은 사원 정보 조회

메인쿼리1: 복수행 서브쿼리가 사용되었으므로, 복수 값과 연산가능한 연산자 사용가능.

아래조건은, 단일 값 연산자인 비교연산자(<) 사용 --> *오류발생*
왜? 오라클 입장에서는, 여러 월급 중에서, 과연 어떤 월급보다 작아야 하는지
판단할 수 없기 때문.
ORA-01427: single-row subquery returns more than one row
salary < (

메인쿼리2: 복수행 서브쿼리가 사용되었으므로, 복수 값과 연산가능한 연산자 사용가능.

아래조건은, 단일값 연산자인 비교연산자(<) 사용 --> *오류발생* 가능하나,
오라클이 반환된 여러 월급 중에서, 가장 작은(최소 급여) 급여를 기준으로,
메인쿼리 조건을 수행가능하도록 ALL 키워드 적용.

결과적으로, 복수행 서브쿼리가 반환한 모든 값 중, 
*최소값 보다 작은* 사원 필터링    
SELECT
    last_name,
    department_id,
    salary
FROM
    employees
WHERE
    salary < ALL (

        -- 복수 행 비상관 서브쿼리: 직책이 IT_PROG인 사원의 월급 반환
        -- 메인쿼리로 결과값 전달
        SELECT
            salary
        FROM
            employees
        WHERE
            job_id = 'IT_PROG'

    );

-- 직책이 IT_PROG인 사원의 월급보다 많은 사원 정보 조회

SELECT
    last_name,
    department_id,
    salary
FROM
    employees
WHERE
    -- 메인쿼리: 복수행 서브쿼리가 사용되었으므로, 복수 값과 연산가능한 연산자 사용가능.
    --
    -- 아래조건은, 단일값 연산자인 비교연산자(>) 사용 --> *오류발생* 가능하나,
    -- 오라클이 반환된 여러 월급 중에서, 가장 큰(최대 급여) 급여를 기준으로,
    -- 메인쿼리 조건을 수행가능하도록 ALL 키워드 적용
    --
    -- 결과적으로, 복수행 서브쿼리가 반환한 모든 값 중, *최대값 보다 큰* 사원 필터링
    salary > ALL (

        -- 복수 행 비상관 서브쿼리: 직책이 IT_PROG인 사원의 월급 반환
        -- 메인쿼리로 결과값 전달
        SELECT
            salary
        FROM
            employees
        WHERE
            job_id = 'IT_PROG'

    );

(3) ANY 연산자 사용한 복수행 서브쿼리

-서브쿼리가 반환한 값 중 하나의 값이 만족하게 만족하면 반환
-ANY 모든데이터들이 최소값보다 크거나 최대값보다 작은 데이터를 만족 할 때 반환
ALL은 ANY의 집한안의 집합이라 할 수있다.

 가. 서브쿼리 반환값이 복수 개.
 나. 서브쿼리에서, < or > 같은 비교연산자 사용하고자 할 때 사용.
 다. 메인쿼리의 비교연산자는 단일 행 연산자이기 때문에,
     메인쿼리의 단일행 연산자에 ANY 키워드 없이 사용하면 오류발생.
 라. ANY 연산자:
     서브쿼리에서 반환된 전체 행들에 대해서, 조건이 하나라도(any)
     만족해야 된다는 것을 의미.
 마. 구분:
     (1) > ANY (서브쿼리)
         - 서브쿼리에서 반환된 모든 데이터보다 큰 데이터 조회
         - 결국, 서브쿼리에서 반환된 모든 데이터 중,
           *최소값보다 큰* 데이터 조회

     (2) < ANY (서브쿼리)
         - 서브쿼리에서 반환된 모든 데이터보다 작은 데이터 조회
         - 결국, 서브쿼리에서 반환된 모든 데이터 중, 
           *최대값보다 작은* 데이터 조회

-- 직책이 IT_PROG인 사원의 최소 월급여보다 큰 사원 정보 조회

SELECT
    last_name,
    department_id,
    salary
FROM
    employees
WHERE
    -- 메인쿼리: 복수행 서브쿼리가 사용되었으므로, 복수 값과 연산가능한 연산자 사용가능.
    --
    -- 아래조건은, 단일값 연산자인 비교연산자(>) 사용 --> *오류발생* 가능하나,
    -- 오라클이 반환된 여러 월급 중에서, 가장 작은(최소 급여) 급여를 기준으로,
    -- 메인쿼리 조건을 수행가능하도록 ANY 키워드 적용
    -- 
    -- 결과적으로, 복수행 서브쿼리가 반환한 모든 값 중, *최소값 보다 큰* 사원 필터링
    salary > ANY (

        -- 복수 행 비상관 서브쿼리: 직책이 IT_PROG인 사원의 월급 반환
        -- 메인쿼리로 결과값 전달
        SELECT
            salary
        FROM
            employees
        WHERE
            job_id = 'IT_PROG'


    );

-- 직책이 IT_PROG인 사원의 최대 월급여보다 작은 사원 정보 조회

SELECT
    last_name,
    department_id,
    salary
FROM
    employees
WHERE
    -- 메인쿼리: 복수행 서브쿼리가 사용되었으므로, 복수 값과 연산가능한 연산자 사용가능.
    --
    -- 아래조건은, 단일값 연산자인 비교연산자(<) 사용 --> *오류발생* 가능하나,
    -- 오라클이 반환된 여러 월급 중에서, 가장 큰(최대 급여) 급여를 기준으로,
    -- 메인쿼리 조건을 수행가능하도록 ANY 키워드 적용
    --
    -- 결과적으로, 복수행 서브쿼리가 반환한 모든 값 중, *최대값 보다 작은* 사원 필터링
    salary < ANY (

        -- 복수 행 비상관 서브쿼리: 직책이 IT_PROG인 사원의 월급 반환
        -- 메인쿼리로 결과값 전달
        SELECT
            salary  -- 이 값이 만일, 1000, 2000, 3000 을 반환한다면
        FROM
            employees
        WHERE
            job_id = 'IT_PROG'

    );

(4) EXISTS 연산자 사용한 복수행 서브쿼리

-EXISTS 단항연산자/ 서브쿼리의 반환결과 조건에 따라 단 하나의 조건이라도 충족한다면 메인쿼리를 전부 반환한다. 단 하나의 조건이라도 만족하지 않으면 메인쿼리를 수행은 하지만 하나도 반환이 안됌.
(WHERE절은 조건에 맞춰 뽑는다. 조건을 극단적으로 만들어줌 )

 가. 서브쿼리 반환값이 복수 개.
 나. 메인쿼리의 값이, 서브쿼리에서 반환된 결과 중에 하나라도
     존재하는지 여부를 확인할 때 사용하는 복수행 연산자.
 다. 만일, 서브쿼리의 반환결과가 하나라도 없으면(false),
     메인쿼리를 수행하지 않음.
 라. 만일, 서브쿼리의 반환결과가 하나라도 있으면(true),
     메인쿼리를 수행.
SELECT
    last_name,
    department_id,
    salary,
    commission_pct
FROM
    employees
WHERE
    -- 메인쿼리: 복수행 서브쿼리가 사용되었으므로, 복수값과 연산가능한 연산자 사용가능.
    --          복수행 연산자로 EXISTS 사용
    --
    -- 모든 사원조회 (if 커밋션을 받는 사원이 한명이라도 있다면...)
    EXISTS (

        -- 복수행 비상관 서브쿼리: 커밋션을 받는 사원번호 반환
        -- 메인쿼리로 결과값 전달
        SELECT
            employee_id --NULL이어도 where절에 충족하는 NULL이라는 속성으로 35개반환
        FROM
            employees
        WHERE
            commission_pct IS NOT NULL

    );
SELECT
   last_name,
   department_id,
   salary
FROM
   employees
WHERE
   -- 모든 사원조회 (if 5000000보다 큰 월급여를 받는 사원이 한명이라도 있다면...)
   EXISTS (        
       -- 복수 행 비상관 서브쿼리: 월급여가 500000보다 큰 사원번호 반환 (*없음*)
       -- 메인쿼리로 결과값 전달(하나도 조회된 결과가 없으므로, false가 전달)
       SELECT 1 --where에 충족하는 열이 무슨 이름으로 해도나옴
       FROM employees
       WHERE salary > 500000
   );

4. 다중컬럼 Sub-query

 가. 서브쿼리에서, 여러 컬럼을 조회하여 반환
 나. 메인쿼리의 조건절에서는, 서브쿼리의 여러 컬럼의 값과 일대일
     매칭되어 조건판단을 수행해야 함.
 다. 메인쿼리의 조건판단방식에 따른 구분:
     (1) Pairwise 방식
         컬럼을 쌍으로 묶어서, 동시에 비교
     (2) Un-pairwise 방식
         컬럼별로 나누어 비교, 나중에 AND 연산으로 처리
SELECT
    last_name,
    department_id,
    salary
FROM
    employees
WHERE
    -- 메인쿼리: 복수행 서브쿼리가 사용되었으므로, 복수 값과 연산가능한 연산자 사용가능 (IN)
    --
    -- 컬럼을 쌍으로 묶어서, 동시에 비교 (**Pairwise 방식**)
    -- 동시에 만족하는 경우에만 참(true)으로 판단.
    --
    -- 결과적으로, 부서별로 가장 많은 월급여를 받는 사원정보 조회
    ( department_id, salary ) IN (
        -- 복수 행 비상관 서브쿼리: 각 부서별, 최대 월급여 반환
        -- 메인쿼리로 결과값 전달
        SELECT
            department_id,
            max(salary)
        FROM
            employees
        GROUP BY
            department_id  -- NULL 그룹도 포함!!
    )
ORDER BY
    2 ASC;

5. 인라인 뷰(Inline View)

-진짜 쓰는 컬럼 등등 만을 이용해 진짜 필요한 결과셋을 만들어 작은 테이블로 재정의 하는 것/ 크기를 줄여 효율적 구성을 돕는다.
-반드시 별칭을 지어야함.

 가. 뷰(View) : 실제 존재하지 않는 가상의 테이블이라 할 수 있음
 나. FROM 절에 사용된 서브쿼리를 의미
 다. 동작방식이 뷰(View)와 비슷하여 붙여진 이름
 라. 일반적으로, FROM 절에는 테이블이 와야 하지만, 서브쿼리가
     마치 하나의 가상의 테이블처럼 사용가능
 마. 장점:
     실제로 FROM 절에서 참조하는 테이블의 크기가 클 경우에,
     필요한 행과 컬럼만으로 구성된 집합(Set)을 재정의하여,
     쿼리를 효율적으로 구성가능.

-- 각 부서별, 총 사원수 / 월급여 총계 / 월급여 평균 조회
-- Oracle Inner Join( Equal Join ) 사용방식

SELECT
    e.department_id,
    sum(salary) AS 총합,
    avg(salary) AS 평균,
    count(*) AS 인원수
FROM
    -- CROSS JOIN(== Cartesian Product) Size: 107 x 27 = 2,889
    employees e,
    departments d
WHERE
    e.department_id = d.department_id
GROUP BY
    e.department_id
ORDER BY
    1 ASC;

-- 위 조인 쿼리를, 좀 더 효율적으로 수행가능한 형식으로 변경
-- 인라인 뷰(Inline View) 사용

SELECT
    e.department_id,
    d.department_name,
    총합,
    평균,
    인원수
FROM
    -- CROSS JOIN(== Cartesian Product) Size: 12 x 27 = 324
    
    (   -- 인라인 뷰(Inline View) 크기: 12
        SELECT
            department_id,
            sum(salary) AS 총합,
            avg(salary) AS 평균,
            count(*) AS 인원수
        FROM
            employees
        GROUP BY
            department_id
    ) e,
    departments d   -- 부서크기: 27
WHERE
    e.department_id = d.department_id       -- 조인조건(공통컬럼지정)
ORDER By
    1 ASC;

자바

컬렉션 프레임워크 (자바 유틸이라는 표준 패키지에 들어있어 매우매우 중요함)

어떤 컬렉션프레임워크를 이용하여 구현할까 고민하는것이 중요함

-List 계열 (순서를 가지며 저장/중복 저장 가능)

특징
1)인덱스로 관리
2)중복해서 객체로 저장하능

----<List간편사용메소드>---------
public class AsListEx {
	public static void main(String[] args) {
		
		List<String> list1 = Arrays.asList("홍길동","신용권","백자바");
		
		for(String name: list1) {
			
			System.out.println(name);
			
		}// enhanced for 
		
//   ----
		
		
		// 기본타입의 값을, List 컬렉션으로 관리하고 싶으면, 
		// 기본타입에 대응되는 Wrapper Type Class를 사용하라!! 
		List<Integer> list2 = Arrays.<Integer>asList(1,2,3,4,5,6,7);
		
		for(int value : list2) {
			
			System.out.println(value);
			
		}// enhanced for 
		
		
	}// main
} // end class

1)ArrayList

-----------<ArrayList  List계열 성질>
public class ArrayListEx {

	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		
//		--
		list.add("Java");
		list.add("JDBC");
		list.add("Servlet/JSP");
		list.add(2,"Database"); // 2번째로 넣으면서 나머지를 뒤로 한칸씩 미룬다. 많으면 많을수록 시간이 늘어난다. 엄청나게 많으면 치명적 
		list.add("MyBATIS");
		
		System.out.println(list);
		//결과: [Java, JDBC, Database, Servlet/JSP, MyBATIS]

//		-- 
	
		int size = list.size();
		System.out.println("총 객체수: " + size);
		// 결과: 총 객체수: 5
//		---
		
		String skill = list.get(2);
		System.out.println("2: " + skill);
		//결과 2: Database
		
//		----
		
		for(int i = 0 ; i < list.size();i++) {
			
			String str = list.get(i);
			
			System.out.println(i + ":" + str);
		} // for
//		결과		
//		0:Java
//		1:JDBC
//		2:Database
//		3:Servlet/JSP
//		4:MyBATIS
		
		for(String str:list) { //Iterable 해야지 enhanced for문 사용가능 -> interface가 정의 되어있는지 찾아봐라 
			
			System.out.println(str);
		} // enhanced for		
		//결과 
//		Java
//		JDBC
//		Database
//		Servlet/JSP
//		MyBATIS
		
		list.remove(2);
		list.remove(2); //지정된 index 요소 삭제 
		list.remove("IBATIS");
		
		System.out.println(list); //결과: [Java, JDBC, MyBATIS]
		
		list.clear();
		list= null;
		
	}//main

}// end class

2)Vector

@AllArgsConstructor
public class Board {
	String subject;
	String content;
	String writer;
	
	
}// end class

// 데이터를 밀고 땡기고는 ArrayList와 동일/ Thread 부분만 다름
public class VectorEx {
	
	public static void main(String[] args) {
		@Cleanup("clear") // 별도로 지정해주면 이 문장의 끝을 만날때 해당 명시된 메소드로 실행해줌. 
		List<Board> list = new Vector<>();

		
		list.add(new Board("제목1", "내용1", "글쓴이1"));
		list.add(new Board("제목2", "내용2", "글쓴이2"));
		list.add(new Board("제목3", "내용3", "글쓴이3"));
		list.add(new Board("제목4", "내용4", "글쓴이4"));
		list.add(new Board("제목5", "내용5", "글쓴이5"));
		
		
		System.out.println(list);
		
		//try-with-resource block은 반드시, 자원객체가 AutoCloseable 인터페이스를 구현하고 있어야한다 
		// List 컬렉션은 사용 불가하다.
//		try(list){
//			;;
//		}// try- with- resources 
		
	}// main

} // end class

3)LinkedList

-Set 계열(집합적 성질을 가진다)

순서 유지 하지 않고
중복 저장 안된다.

-Map 계열

키와 값의 쌍으로 저장
키는 중복 저장이 안된다.

profile
일단 흐자

0개의 댓글