당신은 월에 속한 주차를 구해야한다.

이때 고객사에선 대금결제일이 목요일이라 목요일이 속한 월의 주를 기준으로 주차를 정했으면 좋겠다고 한다.

한 주 단위는 월요일부터 시작 일요일까지다

 

 

위 규칙에 따라 1월30일은 2월 1주차이다.

1월29일은 2월 4주차이다.

 

SELECT TO_DATE(:YYYYMMDD,  'YYYYMMDD' )  /*바인딩변수 받는곳*/                A
     , TO_DATE(:YYYYMMDD,  'YYYYMMDD' )-1                                     B
     , TRUNC(TO_DATE(:YYYYMMDD,  'YYYYMMDD' )-1,'WW')                         C
     , TRUNC(TO_DATE(:YYYYMMDD,  'YYYYMMDD' )-1,'WW')+4  /*목요일보정*/       D
     , TO_CHAR(TRUNC(TO_DATE(:YYYYMMDD,  'YYYYMMDD' )-1,'WW')+4,'W')||'주차'  E
  FROM DUAL;

20230130 주차
20230129 주차

다른 달 검증

4월1일, 4월 2일은 5주차가 나와야한다. 4월 3일부터 1주차가 나와야한다.

 

TRUNC나 TO_CHAR로 날짜를 다루는 것은 굉장히 중요하다. (ROUND도 날짜를 다룰 수 있는데 거의 안씀)

주차를 구하는 것도 별것 아닌 것처럼 보이는데 막상해보면 막힐 수 있다.

 

날짜를 다루는데 도움되는 이전 포스트로 마무리!

https://rkwhr0010.tistory.com/8

 

달력 만드는 과정

2022.05.27 - [개발/오라클 SQL] - 한달 달력 구해보기, 오라클에서 날짜계산, 바인딩 변수 이전 포스트 풀이과정입니다. /*1차 필요한 컬럼 값 만들기*/ SELECT LEVEL AS "DAY" ,TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LE

rkwhr0010.tistory.com

 

 

 

 

 

 

 

 

 

 

 

 

'개발 > 오라클 SQL' 카테고리의 다른 글

WINDOW함수와 DISTINCT조합  (0) 2023.01.19
집계 함수 사용 시 주의사항  (0) 2023.01.15
컬럼 <=> 행 변환  (0) 2023.01.13
숫자 함수 응용  (0) 2023.01.10
자주 쓰는 함수 모음  (1) 2023.01.07

상속 (Inheritance)

기존 클래스로 새로운 클래스를 작성하는 (코드의 재사용)

상속을 통해서 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 있다.

또한 코드를 공통적으로 관리할 있기 때문에 코드의 추가 변경이 용이하다

상속 특성상 상속하면 수록 기능이 많아진다.

 

extends 키워드로 상속한다

확장

생성자와 초기화 블록은 상속되지 않는다.

자바는 단일 상속 객체지향 언어이다.

 

접근제어자 private, default 멤버는 엄밀히 말하면 상속은 되지만, 서브 클래스에서 접근이 불가한 것

클래스의 관계 - 포함 관계(composite)

상속 이외에 클래스를 재사용하는 방법은 클래스의 멤버로 다른 클래스 타입 참조변수를 선언하는

단일 상속만 되는 자바에서 일반적으로 포함 관계가 훨씬 좋다고 여겨진다.

public class Ex1 {
	public static void main(String[] args) {
		//상위 클래스 타입으로 하위 클래스 타입을 다룰 수 있다. 다형성의 핵심
		SuperClass superClass = new SubClass();
		superClass.call();
	}
}
class  SuperClass{
	//일반적으로 멤버변수는 private이 옳다. 데이터 접근은 메서드로 하는 것이 일반적으로 옳다.
	private Composite composite;
	//슈퍼 클래스 생성자는 서브 객체 생성 시 자동으로 호출 된다. 즉, 
	//즉, 슈퍼클래스 객체와 서브 클래스를 묶어 하나 처럼 쓰는 것이다.
	public SuperClass() {
		composite = new Composite();
	}
	public void call() {
		composite.call();
	}
}

class SubClass extends SuperClass{
	//자동으로 컴파일러가 추가 1
//	public SubClass() {
	//자동으로 컴파일러가 추가 2
//		super();
//	}
}

class Composite{
	public void call() {
		System.out.println("구성과 위임");
	}
}

 

구성과 위임

클래스간의 관계 결정하기

클래스를 작성하는데 상속관계를 맺어 줄지, 포함관계를 맺어줄지

 

분류법

상속관계 , is-a 관계, ~는 ~이다, is-a-kind-of , ~는 ~의 분류이다. 이 표현이 더 정확하다는 책도 있다.

포함관계(구성관계) , has-a 관계, ~는 ~를 가지고 있다.

이 내용을 좀 더 이해하려면, 객체지향만을 주제로 한 책을 읽어봐야 한다.

 

앞자리에 하위클래스가 오고 뒤에 상위 클래스가 온다.

 

예시) 오리는 동물이다.  OK , 오리는 동물을 가지고 있다. Not OK

 

객체 지향의 상속이라는 특성을 올바르게 활용하면 리스코프 치환 원칙을 준수하게 된다.

 

단일 상속(single inheritance)

자바는 단일 상속만 허용한다.

다중 상속은 복합적인 기능을 가진 클래스를 쉽게 만들 있다는 장점이 있다

하지만 클래스 간의 관계가 매우 복잡해진다.

 

다중 상속이 된다면 문제점

조상 메소드 이름은 같지만 구현부가 다른 경우 어떤 것을 실행할 것인가? (충돌 문제)

 

자바는 인터페이스로 다중 상속과 유사한 효과를 낼 수 있다.

 

상속과 구성 관계를 확장한 다양한 디자인 패턴도 존재한다.

 

오버라이딩(overriding)

상속받은 조상의 메서드를 자신에 맞게 변경하는

메서드 시그니처는 완전히 동일해야 한다.(반환타입, 매개변수, 이름)

class A{
	A getInstance() {
		return this;
	}
}
class B extends A{
	//단, 자손 타입으로 반환하는 것은 예외적으로 허용된다.
	B getInstance() {
		return this;
	}
}

오버라이딩 조건

  • 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다
  • 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
    조상 클래스 메서드 예외보다 더 상위 예외를 선언할 수 없다는 뜻(예외도 계층이 존재한다)
  • 인스턴스 메서드를 static 메서드로 또는 그 반대로 변경할 수 없다.
class AA{
	void method() throws Exception{	}
	protected void method2(){	}
	static void method3() {}
}


class BB extends AA{
	@Override
	//조상보다 더 많은 예외 안됨
	void method() throws Throwable{
		// TODO Auto-generated method stub
		super.method();
	}
	@Override
	//접근제어자 더 좁게 불가.
	private void method2() {
		// TODO Auto-generated method stub
		super.method2();
	}
	/**
	 * static 멤버는 클래스에 속한 것이지, 인스턴스에 속한게 아니다.
	 * 	따라서 오버라이딩이란 개념이 없다. 야에 별개다. 
	 * AA.method3(), BB.method3() 앞에 변수가 아니라 클래스로 명확히 구분이 가능하다.
	 */
	static void method3() {}
}

 

 

 

 

 

'개발 > 자바(JAVA)' 카테고리의 다른 글

객체 지향 - 6  (0) 2023.02.03
객체 지향 - 5  (0) 2023.02.01
객체 지향 - 3  (0) 2023.01.29
객체 지향 - 2  (0) 2023.01.27
객체 지향 - 1  (0) 2023.01.25

클래스 메서드(static메서드) 인스턴스 메서드

static 붙으면 static 메서드

클래스는 '데이터와 데이터에 관련된 메서드 집합'

따라서 클내스 내에 있는 메서드와 멤버변수는 아주 밀접한 관계가 있다.

 

1. 클래스를 설계할 때. 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙인다. 
생성된 각 인스턴스는 서로 독립적이기 때문에 각 인스턴스의 변수는 서로 다른 값을 유지한다. 그러나 모든 인스턴스에서 같은 값이 유지되어야 하는 변수는 static을 붙여서 클래스변수로 정의해야 한다. 

2. 클래스 변수(static변수)는 인스턴스를 생성하지 않아도 사용할 수 있다. 
static이 붙은 변수(클래스변수)는 클래스가 메모리에 올라갈 때 이미 자동적으로 생성되기 때문이다. 

3. 클래스 메서드 (static 메서드)는 인스턴스 변수를 사용할 수 없다. 
클래스 메서드는 JVM로딩과 동시에 생성된다. 반면에 인스턴스 변수는 객체를 생성해야만 접근할 수 있다.

즉, 클래스 메서드가 존재할 때 반드시 인스턴스 변수가 존재할 거란 보장이 없다.

위와 같은 이유로 인스턴스 멤버는 반드시 클래스 멤버가 존재할 거란 보장이 되기에 아무런 문제가 없다.


4. 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다 
메서드의 작업내용 중에서 인스턴스변수를 필요로 한다면, static을 붙일 수 없다. 반대로 인스턴스변수를 필요로 하지 않는다면 static을 붙이자. 메서드 호출시간이 짧아지므로 성능이 향상된다. static을 안 불인 메서드(인스턴스메서드)는 실행 시 호출되어야할 메서드를 찾는 과정이 추가적으로 필요하기 때문에 시간이 더 걸린다. 

 

오버로딩(overloading)

같은 메서드 이름으로 메서드를 만드는 것, 구분 방법은 매개변수 뿐이다.

매개변수라 함은 매개변수 타입과, 개수이다.

가변인자

내부적으로 배열로 처리

가급적 가변인자는 사용하지 말 것, 명확히 배열 타입이나 컬렉션을 사용할 것

생성자(Constructor)

인스턴스가 생성될 때마다 호출되는 인스턴스 초기화 메서드, 메서드 이름은 클래스 이름과 같다.

 

초기화

초기화를 흔히 깨끗함, 0으로 만들기, 문자열이면 "" 같이 공백으로 넣기 등으로 생각하는 사람이 있다.

아니다. 바로 사용가능한 상태를 만드는 것이 초기화이다.

 

생성자도 근본적으로 메서드다. (반환 값이 없는 메서드)

메서드는 일련의 동작들이다. 즉, 복잡한 초기화를 할 수 있다. 

 

기본 생성자(default constructor)

매개변수가 없는 생성자

생성자가 클래스 안에 하나도 없을 자동으로 컴파일러가 추가해줌

하지만 무조건 직접 만들어주는 것을 권장

매개변수가 있는 생성자를 만들 경우 기본 생성자 추가가 자동으로 안된다. 따라서 무조건 기본 생성자는 수동으로 넣는 것이 좋다.

생성자에서 다른 생성자 호출하기 - this()

생성자 이름 대신 this를 사용하는 것

this는 객체 자신의 주소가 저장되어 있다. 

public class Constructor {
	public Constructor() {
		this(1);
		//반드시 한 개만 호출 가능
//		this(1,2);
	}
	public Constructor(int a) {
		//순환 구조가 생기면 안된다.
//		this();
		this(a,2);
	}
	public Constructor(int a,int b) {
//		super();
	}
}

변수 초기화

기본형은 초기화를 하지 않아도 기본 값이 존재한다.

참조형은 객체 주소이므로 초기값이 존재할 수가 없다. new 연산자로 힙영역에 객체를 생성해야 그 주소가 참조형 변수에 담기기 때문이다. 따라서 null 상태

char는 공백이 초기값이다.  \u0000

 

 

멤버변수의 초기화 방법

  • 명시적 초기화
    선언과 동시에 값을 대입하는 것
  • 생성자
    생성자 호출
  • 초기화 블록
    아무 이름 없이 { } 중괄호만 있는 것

public class Constructor2 {
	int a = 1;
	static {
		System.out.println("JVM에 이 클래스 적재 시 단 한번만 호출, 즉 모든 인스턴스 초기화보다 먼저 호출 됨");
//		System.out.println(a);당연히 사용 못함
	}
	{
		System.out.println(a);
		System.out.println("생성자보다 먼저 호출");
		a = 10;
	}
	public Constructor2() {
		System.out.println(a);
		System.out.println("생성자 호출");
		a = 100;
	}
	public static void main(String[] args) {
		Constructor2 c = new Constructor2();
		System.out.println(c.a);
	}
}

static 초기화 블록이 있는 이유

public class Constructor3 {
	static int a = 1;
	static {
		//클래스 멤버에 대해 복잡한 초기화가 필요할 수 있기 때문
		System.out.println("무언가 복잡한 방법으로 static a를 초기화하고 싶음");
	}
}
클래스 초기화 인스턴스 초기화
기본값 명시적 초기화블록 기본값 명시적 초기화블록 생성자

클래스 초기화는 JVM에 해당 클래스가 적재될 때 단 한 번만 수행 됨

 

 

 

 

 

 

 

 

 

 

 

 

'개발 > 자바(JAVA)' 카테고리의 다른 글

객체 지향 - 5  (0) 2023.02.01
객체 지향 - 4  (0) 2023.01.31
객체 지향 - 2  (0) 2023.01.27
객체 지향 - 1  (0) 2023.01.25
파일 옮기기  (0) 2022.07.25

JVM 메모리 구조

JVM 시스템으로부터 메모리를 할당 받는다

 

1. 메서드 영역(method area) 
프로그램 실행 중 어떤 클래스가 사용되면.(지연로딩)

JVM은 해당 클래스의 클래스파일(*.class)을 읽어서 분석하여 클래스에 대한 정보(클래스 데이터)를 이곳에 저장한다.

이 때. 그 클래스의 클래스변수(class variable)도 이 영역에 함께 생성된다. 

2. 힙(heap) 
인스턴스가 생성되는 공간. 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 생성된다. 
즉 인스턴스변수(instance vanable)들이 생성되는 공간이다. 

3. 호출스택 (call stack 또는 execution stack) 
호출스택은 메서드의 작업에 필요한 메모리 공간을 제공한다. 메서드가 호출되면,
 호출스택에 호출된 메서드를 위한 메모리가 할당되며, 이 메모리는 메서드가 작업을 수행하는 동안 지역변수(매개변수 포함)들과 연산의 중간결과 등을 저장하는데 사용된다. 그리고 메서드가 작업을 마치면 할당되었던 메모리공간은 반환되어 비워진다. 

 

호출 스택의 특징

메서드가 호출되면 수행에 필요한 만큼의 메모리를 스택에 할당받는다. 
메서드가 수행을 마치고나면 사용했던 메모리를 반환하고 스택에서 제거된다. 
호출스택의 제일 위에 있는 메서드가 현재 실행 중인 메서드이다. 
아래에 있는 메서드가 바로 위의 메서드를 호출한 메서드이다. 

public class CallStack {
	public static void main(String[] args) {
		System.out.println(factorial(10));
	}
	public static long factorial(int num) {
		if(num == 0) return 1;
		long result = 0;
		result = num * factorial(--num);
		return result;
	}
}

제일 위가 현재 실행 중 가장 아래가 제일 먼저 호출된 메서드

 

기본형 매개변수- 참조형 매개변수

자바에서 메서드를 호출할 매개변수로 지정한 값은 복사해서 넘겨준다

기본형이면 데이터 복사되지만 참조형이면 주소가 복사된다

 

기본형 매개변수는 변수의 값을 읽기만 할 수 있다.

참조형 매개변수는 변수의 값을 읽고 변경할 수 있다.

public class PrimitiveType {
	public static void main(String[] args) {
		int pValue = 10;
		System.out.println("기본형 변경 전 : "+ pValue);
		int copyPValue = pValue;
		copyPValue = 20;
		System.out.println("기본형 읽고읽은 값 변경 : "+ pValue + "원본에는 영향 안 감");
		System.out.println(pValue == copyPValue);
		
		Referencetype rValue = new Referencetype();
		System.out.println("참조형 변경 전 : "+ rValue);
		Referencetype copyRValue = rValue;
		copyRValue.value = 2000;
		System.out.println("참조형 읽고읽은 값 변경 : "+ rValue + "원본에 영향 감 ");
		System.out.println(rValue == copyRValue);
	}
}

class Referencetype{
	int value = 1000;
	@Override
	public String toString() {
		return value+"";
	}
}
기본형 변경 전 : 10
기본형 읽고읽은 값 변경 : 10원본에는 영향 안 감
false
참조형 변경 전 : 1000
참조형 읽고읽은 값 변경 : 2000원본에 영향 감 
true

재귀호출(recursive call)

메서드 입장에서는 자기 자신을 호출하는 것과 다른 메서드를 호출하는 것은 차이가 없다.

'메서드 호출'이라는 것이 그저 특정 위치에 저장되어 있는 명령들을 수행하는 것일 뿐이기 때문이다.

재귀호출은 무한 루프 위험성이 있어 종료 조건문이 필수적이다.

재귀호출은 반복문보다 성능이 떨어진다. 따라서 재귀호출은 성능적 이점보다 논리적 간결함이 주는 이점이 때만 사용한다.

 

 

 

 

 

 

'개발 > 자바(JAVA)' 카테고리의 다른 글

객체 지향 - 4  (0) 2023.01.31
객체 지향 - 3  (0) 2023.01.29
객체 지향 - 1  (0) 2023.01.25
파일 옮기기  (0) 2022.07.25
변수의 타입  (0) 2022.07.07

자바 객체지향 언어

  • 코드 재사용성이 높다. 
  • 코드 관리가용이하다.
  • 신뢰성이 높은 프로그래밍을 가능하게 한다.

 

객체 지향 프로그래밍

부품에 해당하는 객체를 먼저 만들고, 이걱들을 하나 씩 조립해서 완성된 프로그램을 만드는 기법

 

객체 간의 관계

  • 상속관계
  • 사용관계
  • 집합관계

객체 지향 프로그래밍 특징

    • 캡슐화
      객체의 필드, 메서드를 하나로 묶고, 실제 구현내용을 감추는 것
      접근 제한자를 통해 구현
      감추는(보호하는) 이유는 외부의 잘못된 사용으로 손상을 막기 위함
    • 상속
      상위 객체가 가진 필드와 메서드를 하위 객체에게 물려주는 또한 상위 객체 변경이 하위 객체에게 영향을 미치므로 유지보수성도 상승 한다.
      , 상위 객체를 재사용하여 빠른 설계와 코드 재사용성 상승으로 개발 효율이 올라간다.
    • 다형성
      같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질
      부모 클래스(인터페이스) 타입으로 자식 객체를 다루는 것
    • 추상화
      공통된 성질을 뽑아 상위 타입으로 만든다.

 

클래스와 객체

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

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

 

new 연산자

new 연산자 뒤엔 반드시 생성자를 호출한다.

클래스에 new 연산자를 사용해 객체를 생성, 생성된 객체는 자바 heap 영역에 존재하며, 그 주소 값를 리턴한다.

 

객체의 구성요소

속성 - 멤버변수, 특성, 필드, 상태

기능 - 메서드 , 함수, 행위

 

 

클래스의 구성 멤버

필드

객체가 가져야할 데이터

상태, 정보, 다른 객체의 참조변수

 

생성자

new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 호출되는 메서드

객체 초기화 담당

heap영역에 생성 주소를 리턴

아무 것도 없을 컴파일러가 기본 생성자를 추가해준다.

, 명시적으로 다른 생성자를 만들었으면 기본생성자는 추가 안해준다

명시적 초기화 이유는 복잡 초기화를 위함이다.

 

메소드

객체에 동작에 해당

객체간 데이터 전달

필드 수정 등등

메소드 선언부 - 리턴타입, 메소드이름, 매개변수(파라미터) 선언

이를 시그니처(signature)라고도 한다.

 

클래스의 다른 정의

객체지향의 관점에서 클래스는 객체를 생성하기 위한 , 클래스는 속성과 기능으로 정의된다.

 

클래스를 바라보는 3가지 관점

  • 설계도 
  • 데이터와 함수의 결합
  • 사용자 정의 데이터 타입

변수와 메서드

선언위치 변수종류

클래스 변수, 인스턴스 변수, 지역변수 종류가 있다.

구분 방법은 선언 위치이다.

 

멤버 변수를 제외하고는 전부 지역 변수이며

그중 static 붙은 것을 클래스 변수라 한다.

public class Variables {
	int iv; //인스턴스 변수, 객체와 같은 생명주기 , 힙영역에 위치
	static int cv;// 클래스 변수 JVM과 같은 생명 주기, 메서드 영역에 위치
	
	void method() {
		int lv = 0; //지역변수.  스택 영역에 위치
		//지역변수는 선언과 동시에 초기화를 해줘야 한다.
	}
}

1. 인스턴스 변수(instance variable)

클래스 영역에 선언

클래스의 인스턴스가 생성되었을 생성된다.

각각 독립적인 저장공간을 가진다.(서로 다른 가능)

인스턴스 마다 고유한 상태를 유지해야하는 경우 인스턴스 변수를 사용

객체가 제거 같이 소멸

 

2. 클래스 변수(class variable)

인스턴스 변수 앞에 static 키워드를 붙인

클래스가 메모리에 올라갈 생성되며, 인스턴스 생성 없이 바로 사용 가능

모든 인스턴스가 공통된 저장공간을 공유한다.

JVM 종료될 같이 소멸

 

3. 지역 변수(local variable)

메서드 내에 선언, 메서드 내에서만 사용 가능

메서드 종료 같이 소멸

해당 블록에서만 유효 { }

 

클래스 변수 아무때나 사용가능하다.

프로그램 시작과 동시에 고정으로 생성되기 때문이다.

클래스 변수의 수정은 전역 영향을 미친다.

클래스 변수의 초기화는 묵시적으로 가능하다.

클래스로부터 생성된 객체들이 공유하는 데이터를 클래스 멤버로 만든다.

하나의 메모리를 같이 공유(메서드 영역)

 

인스턴스 변수는 인스턴스가 생성돼야 사용 가능하다.

인스턴스는 힙영역에 동적으로 할당 되기 때문이다.

인스턴스 변수의 변화는 해당 인스턴스만 영향을 미친다.

인스턴스 변수의 초기화는 묵시적으로 가능하다.

필요한 필드나 메서드는 같지만 객체마다 서로 다른 값이 필요한 경우 인스턴스 멤버로 쓴다.

객체마다 별도의 데이터 공간이 할당된다(힙영역)

 

지역 변수는 메서드 구현부 블록 {} 안에서만 유효하다.

스택 영역에 저장되며 블록 {} 벗어나면 소멸한다.

지역 변수의 변화는 해당 메소드에만 영향을 미친다.

지역 변수는 반드시 명시적 초기화 해줘야 한다.

 

메서드

특정 작업을 수행하는 문장을 작업단위로 묶어서 이름을 붙인

 

값을 받아서 처리하고, 결과를 반환

중요한 것은 메서드가 어떤 작업을 수행하는 필요가 없다는 것이다.

, 메서드에 넣을 (입력) 결과(출력) 알면 된다.

그래서 메서드를 내부가 보이지 않는 '블랙박스'라고도 한다.

 

 

메서드를 사용하는 이유 가지

높은 재사용성(reusability)

Java API에서 제공하는 메서드들을 생각해보자

만들어 놓으면 번이고 다른 프로그램에서 사용이 가능하다.

 

중복된 코드 제거

반복되는 코드를 묶어서 하나의 메서드로 작성해 놓으면

반복되는 코드 대신 메서드 호출 번으로 대체가 가능하다.

, 코드량과 코드 유지보수성이 증가한다.

코드 변경에도 유리하다.

 

프로그램 구조화

main()메서드 안에 어플리케이션 코드를 집어넣을 수는 없다.

작업 단위로 나눠서 여러 개의 메서드에 담아 프로그램의 구조를 단순화 시키는 것이 필수적이다.

 

메서드의 선언과 구현

메서드는 크게 부분, 선언부와 구현부로 이뤄져 있다.

void method(){ // 이외 선언부, 선언부의 다른 이름 시그니처
/*{}속이 구현부*/
}

반복적으로 수행되는 여러 문장을 하나의 메서드로 작성

하나의 메서드는 가지 기능만을 수행하도록 작성(재사용, 이식성)

 

반환 값은 있을 수도 있고 없을 수도 있지만

반환 값이 있을 경우 반드시 1개만 반환한다.

만약 여러 개를 값을 반환하고 싶다면 배열이나 객체로 반환한다

리턴 값은 당연히 반환 타입과 일치해야한다.

모든 메서드는 반드시 하나의 return문이 있어야한다.

반환 값이 없는 void경우 컴파일러가 자동으로 추가해 준다.

 

메서드 선언부는 후에 변경사항이 발생하지 않도록 신중히 작성해야한다. 메서드를 호출하는 부분이 전부 변경되기 때문이다.

 

 

 

 

 

 

'개발 > 자바(JAVA)' 카테고리의 다른 글

객체 지향 - 3  (0) 2023.01.29
객체 지향 - 2  (0) 2023.01.27
파일 옮기기  (0) 2022.07.25
변수의 타입  (0) 2022.07.07
변수  (0) 2022.07.03

쇼핑몰을 개발하는 중이라고 가정하자

고객이 배송율 현황을 만들어 달라고 했다.

헤더 행 당일배송 익일배송 총배송 당일배송률
데이터행...        
데이터행...        
데이터행...        
마지막 집계 행        

 

위와 같은 집계 그리드 중 마지막 집계 행에 당일배송율에 대한 주

의점을 알아보자

//DB에서 뽑힌 데이터 갯수 설정
const ROWNUM = 10;
//DB에서 뽑힌 데이터라 가정
var dbData = [];
for (let i = 0; i < ROWNUM; i++) {
    var val1 = Math.floor(Math.random() * 100)+1;
    var val2 = Math.floor(Math.random() * 50)+1;
    var sum = val1+val2;
    var per = Math.round((val1/sum*10000))/100;
    dbData.push({당일배송 : val1, 익일배송: val2 , 총배송 : sum, 당일배송률 : per});
}

console.log(dbData);

위와 같은 데이터에서 마지막 집계 행에 당일배송률에 대한 평균값을 구해야한다.

 

당일배송률 평균을 구하기 위해 "당일배송률 합계 / 전체행 수" 로 나눴다.

var count = 0;
var 잘못된당일배송률평균 = dbData.map(row=>{
    count++;
    return row.당일배송률;
}).reduce((a,b)=>a+b) /count;

console.log('잘못된당일배송률평균',Math.round(잘못된당일배송률평균*100)/100);

과연 올바른 값일까?

 

잘못된 값이다. 당일배송률은 이미 가공된 데이터이다.

그 가공된 데이터에 대한 평균값을 구한 것이지, 전체 모수로하는 당일배송률 평균이 아니다. 

 

올바른 값을 알아보자

 

var 총배송합계 = dbData.map(row=>{
    return row.총배송;
}).reduce((a,b)=>a+b);
console.log('총배송합계',총배송합계);


var 당일배송합계 = dbData.map(row=>{
    return row.당일배송;
}).reduce((a,b)=>a+b);
console.log('당일배송합계',당일배송합계);


var 익일배송합계 = dbData.map(row=>{
    return row.익일배송;
}).reduce((a,b)=>a+b);
console.log('익일배송합계',익일배송합계);

//전체 행 수
var count = 0;
var 잘못된당일배송률평균 = dbData.map(row=>{
    count++;
    return row.당일배송률;
}).reduce((a,b)=>a+b) /count;

console.log('잘못된당일배송률평균',Math.round(잘못된당일배송률평균*100)/100);

console.log('제대로된당일배송률평균',Math.round(당일배송합계/총배송합계 *10000)/100);

잘못된당일배송률평균은 당일배송율평균 간 평균값이 계산된 것이다.

반면에 제대로된당일배송률평균은 전체를 하나의 행으로 집계하고 그 결과를 가공해 평균값을 만들었다.

따라서 전체를 대표하는 평균값이 계산된 것이다.

평균구하기주의점.html
0.00MB

 

 

 

 

 

 

 

 

'개발 > 자바스크립트' 카테고리의 다른 글

구조 분해 할당  (0) 2023.08.21
배열은 객체?  (0) 2023.08.18
반올림 함수  (0) 2023.04.10
자바스크립트 중복제거 - 2  (0) 2022.12.15
자바스크립트 중복 제거  (0) 2022.12.12
SELECT (SELECT MAX(sal) FROM emp) AS MAX
      ,(SELECT MIN(sal) FROM emp) AS MIN
      ,(SELECT AVG(sal) FROM emp) AS AVG
      ,(SELECT SUM(sal) FROM emp) AS SUM
  FROM dual;
-- 위는 극단적인 대조를 위한 예시
SELECT DISTINCT  MAX(sal) OVER()  AS MAX   
     , MIN(sal) OVER()  AS MIN   
     , AVG(sal) OVER()  AS AVG   
     , SUM(sal) OVER()  AS SUM   
  FROM EMP;

결과는 같다. 다만 결과를 산출하는 방식에 차이가 있다.

윈도우 함수는 한 번 참조한 테이블을 버퍼로 활용한다.

 

스칼라 서브쿼리
윈도우 함수

SELECT DISTINCT DEPTNO 
     , MAX(sal) OVER(PARTITION BY DEPTNO)  AS MAX   
     , MIN(sal) OVER(PARTITION BY DEPTNO)  AS MIN   
     , AVG(sal) OVER(PARTITION BY DEPTNO)  AS AVG   
     , SUM(sal) OVER(PARTITION BY DEPTNO)  AS SUM   
  FROM EMP;
 
SELECT DEPTNO
      ,MAX(SAL) AS MAX
      ,MIN(SAL) AS MIN
      ,AVG(SAL) AS AVG
      ,SUM(SAL) AS SUM
  FROM EMP
 GROUP BY DEPTNO;

GROUP BY 사용 시 해당 절에 열거된 컬럼만 사용이 가능하다. 

이런 제약에서 자유롭기 때문에 좀 더 유연하게 결과를 도출할 수 있다.

 

 

'개발 > 오라클 SQL' 카테고리의 다른 글

지정 요일 주차 구하기  (1) 2023.02.01
집계 함수 사용 시 주의사항  (0) 2023.01.15
컬럼 <=> 행 변환  (0) 2023.01.13
숫자 함수 응용  (0) 2023.01.10
자주 쓰는 함수 모음  (1) 2023.01.07
SELECT NUM
     , VALUE
FROM (
      SELECT TRUNC(DBMS_RANDOM.VALUE(1,1000)) NUM 
           , DECODE(MOD(TRUNC(DBMS_RANDOM.VALUE(1,1000)) ,2),0,NULL 
                   ,TRUNC(DBMS_RANDOM.VALUE(1,1000))) VALUE  --짝수면 NULL
        FROM DUAL
      CONNECT BY LEVEL <=10
     );

짝수면 NULL이 나오게 했다.

SELECT 
     DISTINCT AVG(VALUE) OVER() AVG1  --NULL포함 안함
     , AVG(NVL(VALUE,0)) OVER() AVG2  -- NULL포함
     , SUM(VALUE) OVER() / COUNT(VALUE) OVER() AVG3 --NULL포함 안함
     , SUM(VALUE) OVER() / COUNT(*) OVER()     AVG4 --카운트만 NULL포함
     , SUM(VALUE) OVER() / COUNT(NVL(VALUE,0)) OVER() AVG5 -- 카윤트만 NULL 포함
     , COUNT(VALUE) OVER() CN1
     , COUNT(1) OVER() CN2
FROM (
      SELECT TRUNC(DBMS_RANDOM.VALUE(1,1000)) NUM 
           , DECODE(MOD(TRUNC(DBMS_RANDOM.VALUE(1,1000)) ,2),0,NULL 
                   ,TRUNC(DBMS_RANDOM.VALUE(1,1000))) VALUE  --짝수면 NULL
        FROM DUAL
      CONNECT BY LEVEL <=10
     );

기본적으로 집계함수는 NULL 값을 제외한다. 따라서 AVG함수나, COUNT함수는 주의해서 사용해야 한다.

NULL인 값을 포함해서 계산을 하고 싶은 경우도 많기 때문이다.

 

추가로 집계함수의 NULL 처리 방식을 이해하면 아래 중 무엇이 잘못된 사용 방식인지 판별할 수 있다.

SELECT SUM(NVL(123,0)) FROM DUAL;
SELECT NVL(SUM(123), 0) FROM DUAL;

1번 째의 경우 나름 생각한다고 NULL처리를 했지만 DB에 불필요한 부하를 주게 된다.

내부적으로 NULL을 처리하는데 개발자가 NVL을 또 주었으니 불필요한 연산이 들어가게 된다.

이게 행이 많고, 집계함수를 몇 십개 쓴다고 생각해보자. 

 

'개발 > 오라클 SQL' 카테고리의 다른 글

지정 요일 주차 구하기  (1) 2023.02.01
WINDOW함수와 DISTINCT조합  (0) 2023.01.19
컬럼 <=> 행 변환  (0) 2023.01.13
숫자 함수 응용  (0) 2023.01.10
자주 쓰는 함수 모음  (1) 2023.01.07

WITH TMP AS
(
SELECT WORD
       ,SUBSTR(WORD, ROWNUM, 1) COL_TO_ROWS
FROM(
    SELECT 'ADSFGWEQWE' WORD FROM DUAL
    )
CONNECT BY LEVEL <= LENGTH(WORD)
)
, TMP2 AS
(
SELECT DECODE(ROWNUM,1,COL_TO_ROWS) "1"
      ,DECODE(ROWNUM,2,COL_TO_ROWS) "2"
      ,DECODE(ROWNUM,3,COL_TO_ROWS) "3"
      ,DECODE(ROWNUM,4,COL_TO_ROWS) "4"
      ,DECODE(ROWNUM,5,COL_TO_ROWS) "5"
      ,DECODE(ROWNUM,6,COL_TO_ROWS) "6"
      ,DECODE(ROWNUM,7,COL_TO_ROWS) "7"
      ,DECODE(ROWNUM,8,COL_TO_ROWS) "8"
      ,DECODE(ROWNUM,9,COL_TO_ROWS) "9"
      ,DECODE(ROWNUM,10,COL_TO_ROWS) "10"
  FROM TMP
)
--SELECT * FROM TMP2;
SELECT MAX("1")||MAX("2")||MAX("3")||MAX("4")||MAX("5")||
       MAX("6")||MAX("7")||MAX("8")||MAX("9")||MAX("10") ROWS_TO_COL
FROM TMP2;

 

TMP2 결과

TMP2 합친 결과

 

컬럼을 행으로 변환할 때는 행을 반복적으로 실행시켜 나눌 수 있지만 본문 "COL_TO_ROWS"

반대로 합칠 때는 수동으로 입력하는 수 밖에 없다. 본문 "ROWS_TO_COL"

WITH R10 AS --미리 만들어둔 반복용 테이블이라 가정
(
SELECT 1 AS NUM FROM DUAL UNION ALL
SELECT 2 AS NUM FROM DUAL UNION ALL
SELECT 3 AS NUM FROM DUAL UNION ALL
SELECT 4 AS NUM FROM DUAL UNION ALL
SELECT 5 AS NUM FROM DUAL UNION ALL
SELECT 6 AS NUM FROM DUAL UNION ALL
SELECT 7 AS NUM FROM DUAL UNION ALL
SELECT 8 AS NUM FROM DUAL UNION ALL
SELECT 9 AS NUM FROM DUAL UNION ALL
SELECT 10 AS NUM FROM DUAL
)
, TMP AS
(
SELECT WORD
       ,SUBSTR(WORD, ROWNUM, 1) COL_TO_ROWS
FROM(
    SELECT 'ADSFGWEQWE' WORD FROM DUAL
    )
    , R10 --데카르트 곱으로 활용
 WHERE R10.NUM <= LENGTH(WORD)  
--CONNECT BY LEVEL <= LENGTH(WORD)

)
, TMP2 AS
(
SELECT DECODE(ROWNUM,1,COL_TO_ROWS) "1"
      ,DECODE(ROWNUM,2,COL_TO_ROWS) "2"
      ,DECODE(ROWNUM,3,COL_TO_ROWS) "3"
      ,DECODE(ROWNUM,4,COL_TO_ROWS) "4"
      ,DECODE(ROWNUM,5,COL_TO_ROWS) "5"
      ,DECODE(ROWNUM,6,COL_TO_ROWS) "6"
      ,DECODE(ROWNUM,7,COL_TO_ROWS) "7"
      ,DECODE(ROWNUM,8,COL_TO_ROWS) "8"
      ,DECODE(ROWNUM,9,COL_TO_ROWS) "9"
      ,DECODE(ROWNUM,10,COL_TO_ROWS) "10"
  FROM TMP
)
--SELECT * FROM TMP2;
SELECT MAX("1")||MAX("2")||MAX("3")||MAX("4")||MAX("5")||
       MAX("6")||MAX("7")||MAX("8")||MAX("9")||MAX("10") ROWS_TO_COL
FROM TMP2;

CONNECT BY 를 꼭 안쓰더라도 위 처럼 사용하는 경우도 많다.

'개발 > 오라클 SQL' 카테고리의 다른 글

WINDOW함수와 DISTINCT조합  (0) 2023.01.19
집계 함수 사용 시 주의사항  (0) 2023.01.15
숫자 함수 응용  (0) 2023.01.10
자주 쓰는 함수 모음  (1) 2023.01.07
SELECT 문으로 SQL문 만들기  (0) 2023.01.05
	SELECT 
	       MONTH 
	     , EXTRACT (MONTH FROM MONTH) /3 M1
	     , CEIL(EXTRACT (MONTH FROM MONTH) /3) M2
	     , MOD(EXTRACT (MONTH FROM MONTH) ,3) M3
	 FROM(
		SELECT ADD_MONTHS(TRUNC(SYSDATE ,'YYYY'), LEVEL-1) MONTH  
		 FROM DUAL
		CONNECT BY LEVEL <= 12
	     )

리포트나 통계를 낼 때 그룹핑을 위한 값을 생성할 때 숫자함수가 유용하다.

 

SELECT M2
	  ,M3
	  ,DECODE(M3, 1, M2||'분기') M4
	  ,MONTH
 FROM(
	SELECT 
	       MONTH 
	     , EXTRACT (MONTH FROM MONTH) /3 M1
	     , CEIL(EXTRACT (MONTH FROM MONTH) /3) M2
	     , MOD(EXTRACT (MONTH FROM MONTH) ,3) M3
	 FROM(
		SELECT ADD_MONTHS(TRUNC(SYSDATE ,'YYYY'), LEVEL-1) MONTH  
		 FROM DUAL
		CONNECT BY LEVEL <= 12
	     )
     )
;

 

 

 

 

 

 

 

'개발 > 오라클 SQL' 카테고리의 다른 글

집계 함수 사용 시 주의사항  (0) 2023.01.15
컬럼 <=> 행 변환  (0) 2023.01.13
자주 쓰는 함수 모음  (1) 2023.01.07
SELECT 문으로 SQL문 만들기  (0) 2023.01.05
중복 데이터 삭제  (0) 2023.01.03

+ Recent posts