아마도 날짜로만 쿼리 포스트는 마지막일 듯 합니다.

 

SELECT 
	TO_DATE(:ST_YYYYMM, 'YYYYMM') "시작일"
	,ADD_MONTHS(TO_DATE(:ET_YYYYMM , 'YYYYMM'),1)-1 "마지막일"
FROM DUAL;

 

시작점과 끝점 구하기


 

SELECT 
	TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL "DAY"
	,ADD_MONTHS(TO_DATE(:ET_YYYYMM , 'YYYYMM'),1)-1 "마지막일"
	,COUNT(*) OVER()
FROM DUAL
CONNECT BY TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL <= ADD_MONTHS(TO_DATE(:ET_YYYYMM , 'YYYYMM'),1)-1;

 

시작점과 끝점 사이 ROW값 구하기


SELECT 
	TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL "DAY"
	,TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') "속한 요일"
	,TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL, 'D') "속한 주"
	,TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL, 'MM') "속한 달"
FROM DUAL
CONNECT BY TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL <= ADD_MONTHS(TO_DATE(:ET_YYYYMM , 'YYYYMM'),1)-1;

필요한 컬럼 값 구하기

 

 


 

SELECT 
	DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 1, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD')) "일"
	,DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 2, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD')) "월"
	,DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 3, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD')) "화"
	,DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 4, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD')) "수"
	,DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 5, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD')) "목"
	,DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 6, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD')) "금"
	,DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 7, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD')) "토"
	,TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL "DAY"
	,TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') "속한 요일"
	,TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL, 'D') "속한 주"
	,TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL, 'MM') "속한 달"
FROM DUAL
CONNECT BY TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL <= ADD_MONTHS(TO_DATE(:ET_YYYYMM , 'YYYYMM'),1)-1;

"DAY" 행을 DECODE로 강제로 주 단위로 찢기

 


SELECT 
	TO_CHAR(DECODE(MIN(TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD')),1, MIN(TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL, 'MM'))),'MM') "달"
	,RANK() OVER(PARTITION BY  TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL, 'MM') ORDER BY MIN(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL)) || '주차' "주차"
	,SUM(DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 1, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD'))) "일"
	,SUM(DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 2, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD'))) "월"
	,SUM(DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 3, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD'))) "화"
	,SUM(DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 4, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD'))) "수"
	,SUM(DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 5, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD'))) "목"
	,SUM(DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 6, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD'))) "금"
	,SUM(DECODE( TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'D') , 7, TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL,'DD'))) "토"
FROM DUAL
CONNECT BY TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL <= ADD_MONTHS(TO_DATE(:ET_YYYYMM , 'YYYYMM'),1)-1
GROUP BY TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL, 'MM'),TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL, 'D')
ORDER BY MIN(TO_DATE(:ST_YYYYMM, 'YYYYMM')-1+LEVEL)
;

 

찢은 컬럼을 GROUP BY 표현식으로 하나의 행으로 합침 

부가적으로  몇 월, 몇 주차 표시


 

마무리

날짜를 기준으로 그룹화를 하는 것은 꽤나 실전적인 쿼리입니다.

조금만 생각해보면 답이 나옵니다. 내가 쇼핑몰을 개발하던, 공장 재고관리를 하던, ... 고객이 원하는 대부분의 통계는 날짜 더나아가 시간 정보로 보길 원하거든요. 

이렇게 시간기준으로 집계한 원본 소스값에  WHERE 절을 추가해서 검색 조건을 달게 됩니다.

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

문자열 다루기 핵심 TRANSLATE  (1) 2022.11.25
IN, NOT IN, EXISTS, NOT EXISTS  (0) 2022.11.10
마이바티스 null 체크  (0) 2022.09.28
정규식을 통한 Mybatis Sql Injection 처리  (0) 2022.06.29
달력 만드는 과정  (0) 2022.06.02

2022.05.27 - [개발/오라클 SQL] - 한달 달력 구해보기, 오라클에서 날짜계산, 바인딩 변수

이전 포스트 풀이과정입니다.

 

/*1차 필요한 컬럼 값 만들기*/
SELECT 
	LEVEL AS "DAY"
	,TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'DD') AS "TO_CHAR" 
	,EXTRACT(DAY FROM TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1) AS "EXTRACT"
	,TO_CHAR(TO_DATE(:ST_YYYYMM+1, 'YYYYMM')-1, 'DD') AS "마지막일" 
	,TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D') AS "요일 인덱스"
	,TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D') AS "내가 속한날 첫 일"
FROM DUAL
CONNECT BY LEVEL <=TO_CHAR(TO_DATE(:ST_YYYYMM+1, 'YYYYMM')-1, 'DD');

 

 

"DAY", "TO_CHAR", "EXTRACT" 는 같은 값을 다르게 뽑는 방식입니다. 

 

추가로 오른쪽 정렬이 숫자, 왼쪽 정렬이 문자열을 의미합니다.

 

보통 모든 변환은 TO_CHAR를 제일 많이 사용합니다. 지원하는 기능도 많고 문자열이기 때문에 매개체 역할도 가능하기 때문입니다.


 

/*DECODE 사용한 피벗 */
SELECT
	"내가 속한날 첫 일" 
	,DECODE("요일 인덱스", 1 , "DAY") AS "일"
	,DECODE("요일 인덱스", 2 , "DAY") AS "월"
	,DECODE("요일 인덱스", 3 , "DAY") AS "화"
	,DECODE("요일 인덱스", 4 , "DAY") AS "수"
	,DECODE("요일 인덱스", 5 , "DAY") AS "목"
	,DECODE("요일 인덱스", 6 , "DAY") AS "금"
	,DECODE("요일 인덱스", 7 , "DAY") AS "토"
FROM
	(
	SELECT 
		LEVEL AS "DAY"
		,TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'DD') AS "TO_CHAR" 
		,EXTRACT(DAY FROM TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1) AS "EXTRACT"
		,TO_CHAR(TO_DATE(:ST_YYYYMM+1, 'YYYYMM')-1, 'DD') AS "마지막일" 
		,TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D') "요일 인덱스"
		,TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D') AS "내가 속한날 첫 일"
	FROM DUAL
	CONNECT BY LEVEL <=TO_CHAR(TO_DATE(:ST_YYYYMM+1, 'YYYYMM')-1, 'DD')
	)
ORDER BY DAY
;


/*GROUP BY 내가 속한날 첫 일_ 로 컬럼 값 압축*/
SELECT
	"내가 속한날 첫 일"  
	,SUM(DECODE("요일 인덱스", 1 , "DAY")) AS "일"
	,MIN(DECODE("요일 인덱스", 2 , "DAY")) AS "월"
	,MAX(DECODE("요일 인덱스", 3 , "DAY")) AS "화"
	,SUM(DECODE("요일 인덱스", 4 , "DAY")) AS "수"
	,MIN(DECODE("요일 인덱스", 5 , "DAY")) AS "목"
	,MAX(DECODE("요일 인덱스", 6 , "DAY")) AS "금"
	,SUM(DECODE("요일 인덱스", 7 , "DAY")) AS "토"
FROM
	(
	SELECT 
		LEVEL AS "DAY"
		,TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'DD') AS "TO_CHAR" 
		,EXTRACT(DAY FROM TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1) AS "EXTRACT"
		,TO_CHAR(TO_DATE(:ST_YYYYMM+1, 'YYYYMM')-1, 'DD') AS "마지막일" 
		,TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D') "요일 인덱스"
		,TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D') AS "내가 속한날 첫 일"
	FROM DUAL
	CONNECT BY LEVEL <=TO_CHAR(TO_DATE(:ST_YYYYMM+1, 'YYYYMM')-1, 'DD')
	)
GROUP BY "내가 속한날 첫 일"
ORDER BY MIN(DAY)
;


마지막으로 인라인뷰 없이 똑같은 결과를 만들기입니다. 

위 SQL을 기반으로 만들어 보기실 권장합니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

*인라인뷰 사용 안한 최종 쿼리*/
SELECT 
	TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D') AS "내가 속한날 첫 일"
	,SUM(DECODE(TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D'), 1 , LEVEL)) AS "일"
	,MIN(DECODE(TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D'), 2 , LEVEL)) AS "월"
	,MAX(DECODE(TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D'), 3 , LEVEL)) AS "화"
	,SUM(DECODE(TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D'), 4 , LEVEL)) AS "수"
	,MIN(DECODE(TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D'), 5 , LEVEL)) AS "목"
	,MAX(DECODE(TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D'), 6 , LEVEL)) AS "금"
	,SUM(DECODE(TO_CHAR(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D'), 7 , LEVEL)) AS "토"
FROM DUAL
CONNECT BY LEVEL <=TO_CHAR(TO_DATE(:ST_YYYYMM+1, 'YYYYMM')-1, 'DD')
GROUP BY TRUNC(TO_DATE(:ST_YYYYMM, 'YYYYMM')+LEVEL-1, 'D') 
ORDER BY MIN(LEVEL)
;

 

 

 

 

 

 

 

 

 

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class FileDirectoryEx01 {
	static int dirCount = 0;
	static int fileCount = 0;
	
	public static void main(String[] args) throws IOException {
		
		Long startTime = System.currentTimeMillis();
		dirSearch("C:\\spring");
		System.out.println("디렉토리 수		: "+ dirCount);
		System.out.println("파일 수		: "+ fileCount);
		System.out.println("소요시간           : "+ ((System.currentTimeMillis()-startTime)/1000));
		
	}
	
	public static void dirSearch(String dirName) throws MalformedURLException {
		File file = new File(dirName);
		
		for(File f:file.listFiles()) {
			formatter(f);
			if(f.isDirectory()) {
				dirSearch(f.toString());
			}
		}
	}
	
	public static void formatter(File file) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		StringBuilder sb = new StringBuilder(100);
		sb.append(df.format(new Date(file.lastModified())));
		if(file.isDirectory()) {
			sb.append(" [DIR] ");
			dirCount++;
		}else {
			fileCount++;
			sb.append(file.canRead() ? " [R": "[ ");
			sb.append(file.canWrite() ? "W" : " ");
			sb.append(file.canExecute() ? "E]" : " ]");
		}
		
		System.out.printf("%s %6s %s %n", sb.toString(), file.length(), file.toString() );
		
	}
}


핵심 키워드

  • 재귀
  • StringBuilder 내부 버퍼
  • 날짜 형식화

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

파일 옮기기  (0) 2022.07.25
변수의 타입  (0) 2022.07.07
변수  (0) 2022.07.03
자바란?  (0) 2022.07.02
File  (0) 2022.05.26

목적


기본적인 File 입출력을 사용해보면서 익히기

 

 

기본 사용


package file;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.file.FileSystems;

public class FileEx01 {
	public static void main(String[] args) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		
		try {
			fis = new FileInputStream("input.txt");
			System.out.println("운영체제별 디렉토리 구분자 ::: "+FileSystems.getDefault().getSeparator());
			fos = new FileOutputStream("src\\file/output.txt");
			int i;
			while((i=fis.read()) != -1 ) {
				fos.write(i);
			}
		}catch (Exception e) {
			System.out.println(e.getMessage());
		}finally {
			try {
				fis.close();
				fos.close();/*반드시 닫아줘야 합니다.*/
			} catch (Exception e2) {
				System.out.println(e2.getMessage());
			}
		}
	}
}

 

 

응용 사용


public class FileEx02 {
	public static void main(String[] args) {
		
		Long startTime = System.currentTimeMillis();
		
		try (BufferedInputStream bis= new BufferedInputStream(new FileInputStream("C:\\Users\\kks\\Downloads\\input\\원노트.zip"));
			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:\\\\Users\\\\kks\\\\Downloads\\\\output\\\\원노트.zip"), 1024*4);
				) {
			int i;
			
			while((i=bis.read()) != -1 ) {
				bos.write(i);
				
			}
		}catch (Exception e) {
			System.out.println(e.getMessage());
		}finally {
			System.out.println("버퍼 사용 파일 입출력 완료 ::: " + ((System.currentTimeMillis()-startTime)/1000 ));
		}
	}
}

결과 = 버퍼 사용 파일 입출력 완료 ::: 35

파일 크기는 1.67GB

 

package file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.net.URL;

public class FileEx02 {
	public static void main(String[] args) {
		
		Long startTime = System.currentTimeMillis();
		
		try (BufferedInputStream bis= new BufferedInputStream(new URL("https://upload.wikimedia.org/wikipedia/commons/6/62/%EC%84%9C%EC%9A%B8%ED%8A%B9%EB%B3%84%EC%8B%9C_%EC%A0%84%EA%B2%BD_%EC%82%AC%EC%A7%84_%EC%82%AC%EB%B3%B8_-%EC%84%9C%EC%9A%B8%EC%84%B1%EA%B3%BD1.jpg").openStream());
			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src/pic.jpg"), 1024*4);
				) {
			int i;
			
			while((i=bis.read()) != -1 ) {
				bos.write(i);
				
			}
		}catch (Exception e) {
			System.out.println(e.getMessage());
		}finally {
			System.out.println("무료 사진 가져오기!");
		}
	}
}

데이터 소스가 로컬이건, 인터넷이건 결국은 입출력 구조를 따릅니다.

 

 

 

 

 

핵심 키워드

  • try - with - resource 
  • AutoCloseable, Closeable
  • 버퍼스트림(보조스트림)

 

 
 

닫기 가능

 

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

파일 옮기기  (0) 2022.07.25
변수의 타입  (0) 2022.07.07
변수  (0) 2022.07.03
자바란?  (0) 2022.07.02
폴더, 파일 수 탐색  (0) 2022.05.27

책 처럼 목차를 지켜가면서 게시물을 올리지는 않습니다.

그때그때 복습한 내용이나 올리고 싶은 내용을 올리겠습니다!!

 

'잡담' 카테고리의 다른 글

강의료에 대한 고찰  (0) 2023.02.16
복습이되네  (0) 2022.10.02

+ Recent posts