728x90
반응형

📝 문제

더보기

1. 문제 설명

 코니는 영어 단어가 적힌 카드 뭉치 두 개를 선물로 받았습니다. 코니는 다음과 같은 규칙으로 카드에 적힌 단어들을 사용해 원하는 순서의 단어 배열을 만들 수 있는지 알고 싶습니다.

  • 원하는 카드 뭉치에서 카드를 순서대로 한 장씩 사용합니다.
  • 한 번 사용한 카드는 다시 사용할 수 없습니다.
  • 카드를 사용하지 않고 다음 카드로 넘어갈 수 없습니다.
  • 기존에 주어진 카드 뭉치의 단어 순서는 바꿀 수 없습니다.

예를 들어 첫 번째 카드 뭉치에 순서대로 ["i", "drink", "water"], 두 번째 카드 뭉치에 순서대로 ["want", "to"]가 적혀있을 때 ["i", "want", "to", "drink", "water"] 순서의 단어 배열을 만들려고 한다면 첫 번째 카드 뭉치에서 "i"를 사용한 후 두 번째 카드 뭉치에서 "want"와 "to"를 사용하고 첫 번째 카드뭉치에 "drink"와 "water"를 차례대로 사용하면 원하는 순서의 단어 배열을 만들 수 있습니다.

문자열로 이루어진 배열 cards1, cards2와 원하는 단어 배열 goal이 매개변수로 주어질 때, cards1과 cards2에 적힌 단어들로 goal를 만들 있다면 "Yes"를, 만들 수 없다면 "No"를 return하는 solution 함수를 완성해주세요.


2. 제한사항

  • 1 ≤ cards1의 길이, cards2의 길이 ≤ 10
    • 1 ≤ cards1[i]의 길이, cards2[i]의 길이 ≤ 10
    • cards1과 cards2에는 서로 다른 단어만 존재합니다.
  • 2 ≤ goal의 길이 ≤ cards1의 길이 + cards2의 길이
    • 1 ≤ goal[i]의 길이 ≤ 10
    • goal의 원소는 cards1과 cards2의 원소들로만 이루어져 있습니다.
  • cards1cards2goal의 문자열들은 모두 알파벳 소문자로만 이루어져 있습니다.

3. 입출력 예

cards1 cards2 goal result
["i", "drink", "water"] ["want", "to"] ["i", "want", "to", "drink", "water"] "Yes"
["i", "water", "drink"] ["want", "to"] ["i", "want", "to", "drink", "water"] "No"

 


4. 입출력 예 설명

  • 입출력 예 #1
     본문과 같습니다.
  • 입출력 예 #2
     cards1에서 "i"를 사용하고 cards2에서 "want"와 "to"를 사용하여 "i want to"까지는 만들 수 있지만 "water"가 "drink"보다 먼저 사용되어야 하기 때문에 해당 문장을 완성시킬 수 없습니다. 따라서 "No"를 반환합니다.

📝 작성한 코드

 처음엔 HaspMap을 써보려다 실패하고 작성한 코드인데, 다른 분들이 작성한 걸 보니 HashMap을 써서 푸신 분이 꽤나 있었다. 이 외에도 Queue(큐)라는 클래스를 사용하신 분들이 많았다. 큐는 선입선출법의 성격을 지닌 자료구조라고 한다. 문제의 조건에서 카드 뭉치를 순서대로 한장 씩 사용한다고 했으므로, 큐의 성격을 이용하여 문제를 풀어보면 좋을 것 같다.
 
 내가 작성한 코드는 간단히 for문을 돌려 진행되는 코드이다. 처음에는 goal[i]와 cards[i]를 비교해보면 된다고 생각했는데, 인덱스범위 오류가 나는 걸 보고 cards의 길이는 goal의 길이보다 작다는 것을 깨달았다. 그래서 cards의 인덱스 값을 따로 변수 (card1Index)로 주고 cards1[card1Index]이 goal에 들어있는 값과 일치하면 그 인덱스에 해당하는 cards의 값은 다시 사용할 수 없도록 +1을 해주었다. 그리고 answer의 초기값을 Yes로 설정해두고 if문의 조건1과 2가 제대로 실행되않으면 No를 반환하도록 하였다.
 

class Solution {
    public String solution(String[] cards1, String[] cards2, String[] goal) {
        String answer = "Yes";
        int card1Index = 0;
        int card2Index = 0;
 
        for (int i = 0; i < goal.length; i++) {
            if (card1Index < cards1.length && cards1[card1Index].equals(goal[i])){
                card1Index++;
            }
            else if(card2Index < cards2.length && cards2[card2Index].equals(goal[i])){
                card2Index++;
            }
            else {
                answer = "No";
            }
        }    
                 
        return answer;
    }
}

 

📝 공부해 볼 코드

Queue(큐)를 사용한 코드.
큐는 데이터를 일시적으로 쌓아두기 위한 자료구조로 스택과는 다르게 FIFO(First In First Out)의 형태를 가진다. FIFO 형태는 뜻 그대로 먼저 들어온 데이터가 가장 먼저 나가는 선입선출을 의미한다.
 
<코드 설명>

  1. Queue<String> queue1 및 Queue<String> queue2를 생성하고, 각각 cards1 및 cards2 배열을 큐로 변환하여 초기화
  2. for (String g : goal) 루프를 통해 목표 배열을 순회한다. 루프 내에서는 peek()라는 메서드를 통해 현재 목표 g가 queue1 또는 queue2의 맨 앞에 있는 카드와 일치하는지 확인한다.
  3. * queue.peek(); // queue의 첫번째 값 참조
  4. 만약 g가 queue1의 맨 앞에 있는 카드와 일치한다면, queue1.poll()를 사용하여 큐에서 해당 카드를 제거한다. 이어서 continue 키워드를 사용하여 다음 목표로 이동한다.
  5. * queue.poll(); // queue에 첫번째 값을 반환하고 제거 비어있다면 null
  6. 만약 g가 queue2의 맨 앞에 있는 카드와 일치한다면, queue2.poll()를 사용하여 큐에서 해당 카드를 제거한다. 이어서 continue 키워드를 사용하여 다음 목표로 이동한다.
  7. 만약 g가 어느 큐에도 일치하지 않는다면, "No"를 반환하며 프로그램을 종료시킨다
  8. 모든 목표를 순회한다면, "Yes"를 반환한다.
import java.util.*;

class Solution {
    public String solution(String[] cards1, String[] cards2, String[] goal) {
        String answer = "";

        Queue<String> queue1 = new LinkedList<>(Arrays.asList(cards1));
        Queue<String> queue2 = new LinkedList<>(Arrays.asList(cards2));

        for (String g : goal) {
            if (g.equals(queue1.peek())) {
                queue1.poll();
                continue;
            } else if (g.equals(queue2.peek())) {
                queue2.poll();
                continue;
            }
            return "No";
        }

        return "Yes";
    }
}

 

Queue(큐) 참고 주소
https://coding-factory.tistory.com/602

728x90
반응형
728x90
반응형

📝 문제

더보기

1. 문제 설명

코딩테스트를 준비하는 머쓱이는 프로그래머스에서 문제를 풀고 나중에 다시 코드를 보면서 공부하려고 작성한 코드를 컴퓨터 바탕화면에 아무 위치에나 저장해 둡니다. 저장한 코드가 많아지면서 머쓱이는 본인의 컴퓨터 바탕화면이 너무 지저분하다고 생각했습니다. 프로그래머스에서 작성했던 코드는 그 문제에 가서 다시 볼 수 있기 때문에 저장해 둔 파일들을 전부 삭제하기로 했습니다.

컴퓨터 바탕화면은 각 칸이 정사각형인 격자판입니다. 이때 컴퓨터 바탕화면의 상태를 나타낸 문자열 배열 wallpaper가 주어집니다. 파일들은 바탕화면의 격자칸에 위치하고 바탕화면의 격자점들은 바탕화면의 가장 왼쪽 위를 (0, 0)으로 시작해 (세로 좌표, 가로 좌표)로 표현합니다. 빈칸은 ".", 파일이 있는 칸은 "#"의 값을 가집니다. 드래그를 하면 파일들을 선택할 수 있고, 선택된 파일들을 삭제할 수 있습니다. 머쓱이는 최소한의 이동거리를 갖는 한 번의 드래그로 모든 파일을 선택해서 한 번에 지우려고 하며 드래그로 파일들을 선택하는 방법은 다음과 같습니다.

  • 드래그는 바탕화면의 격자점 S(lux, luy)를 마우스 왼쪽 버튼으로 클릭한 상태로 격자점 E(rdxrdy)로 이동한 뒤 마우스 왼쪽 버튼을 떼는 행동입니다. 이때, "점 S에서 점 E로 드래그한다"고 표현하고 점 S와 점 E를 각각 드래그의 시작점, 끝점이라고 표현합니다.
  • 점 S(luxluy)에서 점 E(rdxrdy)로 드래그를 할 때, "드래그 한 거리"는 |rdx lux| + |rdy luy|로 정의합니다.
  • 점 S에서 점 E로 드래그를 하면 바탕화면에서 두 격자점을 각각 왼쪽 위, 오른쪽 아래로 하는 직사각형 내부에 있는 모든 파일이 선택됩니다.

예를 들어 wallpaper = [".#...", "..#..", "...#."]인 바탕화면을 그림으로 나타내면 다음과 같습니다

이러한 바탕화면에서 다음 그림과 같이 S(0, 1)에서 E(3, 4)로 드래그하면 세 개의 파일이 모두 선택되므로 드래그 한 거리 (3 - 0) + (4 - 1) = 6을 최솟값으로 모든 파일을 선택 가능합니다.

(0, 0)에서 (3, 5)로 드래그해도 모든 파일을 선택할 수 있지만 이때 드래그 한 거리는 (3 - 0) + (5 - 0) = 8이고 이전의 방법보다 거리가 늘어납니다.

 

머쓱이의 컴퓨터 바탕화면의 상태를 나타내는 문자열 배열 wallpaper가 매개변수로 주어질 때 바탕화면의 파일들을 한 번에 삭제하기 위해 최소한의 이동거리를 갖는 드래그의 시작점과 끝점을 담은 정수 배열을 return하는 solution 함수를 작성해 주세요. 드래그의 시작점이 (lux, luy), 끝점이 (rdx, rdy)라면 정수 배열 [lux, luy, rdx, rdy]를 return하면 됩니다.


2. 제한사항

  • 1 ≤ wallpaper의 길이 ≤ 50
  • 1 ≤ wallpaper[i]의 길이 ≤ 50
    wallpaper의 모든 원소의 길이는 동일합니다.
  • wallpaper[i][j]는 바탕화면에서 i + 1행 j + 1열에 해당하는 칸의 상태를 나타냅니다.
  • wallpaper[i][j]는 "#" 또는 "."의 값만 가집니다.
  • 바탕화면에는 적어도 하나의 파일이 있습니다.
  • 드래그 시작점 (luxluy)와 끝점 (rdxrdy)는 lux rdxluy rdy를 만족해야 합니다.

3. 입출력 예

wallpaper result
[".#...", "..#..", "...#."] [0, 1, 3, 4]
["..........", ".....#....", "......##..", "...##.....", "....#....."] [1, 3, 5, 8]
[".##...##.", "#..#.#..#", "#...#...#", ".#.....#.", "..#...#..", "...#.#...", "....#...."] [0, 0, 7, 9]
["..", "#."] [1, 0, 2, 1]

 

4. 입출력 예

  • 입출력 예 #1
     문제 설명의 예시와 같은 예제입니다. (0, 1)에서 (3, 4)로 드래그 하면 모든 파일을 선택할 수 있고 드래그 한 거리는 6이었고, 6보다 적은 거리로 모든 파일을 선택하는 방법은 없습니다. 따라서 [0, 1, 3, 4]를 return합니다.

  • 입출력 예 #2
     예제 2번의 바탕화면은 다음과 같습니다.(1, 3)에서 (5, 8)로 드래그하면 모든 파일을 선택할 수 있고 이보다 적은 이동거리로 모든 파일을 선택하는 방법은 없습니다. 따라서 가장 적은 이동의 드래그로 모든 파일을 선택하는 방법인 [1, 3, 5, 8]을 return합니다.

 

  • 입출력 예 #3
     예제 3번의 바탕화면은 다음과 같습니다.모든 파일을 선택하기 위해선 바탕화면의 가장 왼쪽 위 (0, 0)에서 가장 오른쪽 아래 (7, 9)로 드래그 해야만 합니다. 따라서 [0, 0, 7, 9]를 return합니다.

 

  • 입출력 예 #4
     예제 4번의 바탕화면은 다음과 같이 2행 1열에만 아이콘이 있습니다.이를 드래그로 선택하기 위해서는 그 칸의 왼쪽 위 (1, 0)에서 오른쪽 아래 (2, 1)로 드래그 하면 됩니다. (1, 0)에서 (2, 2)로 드래그 해도 아이콘을 선택할 수 있지만 이전보다 이동거리가 늘어납니다. 따라서 [1, 0, 2, 1]을 return합니다.

✏️작성한 코드

코드 풀이를 해보자.

일단 X, Y를 행과 열로 생각한다.

  •  int[] X = new int[wallpaper.length]; 
    wallpaper 배열에 들어가 있는 값의 길이 만큼 X, Y도 출력되서 나오므로 X, Y를 wallpaper 만큼의 길이를 가진 리스트로 설정했다.
  • int xMin = Integer.MAX_VALUE;
    X, Y에 들어간 값 중 행의 최솟값과 행의 최댓값, 열의 최솟값과 열의 최댓값을 찾아야 하므로 각각을 변수로 설정한다.  Integer.MAX_VALUE는 JAVA에서의 정수 최댓값을 의미하기 때문에 최솟값을 구하려고 할 때 MAX_VALUE와 비교해야 한다.

  • for 문
    중첩된 루프를 사용하여 wallpaper 배열을 순회하면서 '#' 문자를 찾고, 해당 위치의 행과 열을 XY 배열에 저장하고 최솟값과 최댓값을 업데이트합니다.

  •  Math.min(A, X[i])
    Math.min(a, b)은 두 인자 값 중 작은 값을 리턴한다. 즉, A가 Integer.MAX_VALUE 이므로 X[i]이 그보다 더 클 수 없다. 그러므로 처음 들어오는 X[i]의 값이 A로 리턴되면서 새로 들어오는 X[i]과 비교하여 최소값을 반환하게 된다.

  • xMax = Math.max(C, X[i]+1);
    Max 값에 1을 더해준 이유는 파일이 교차되는 점에 위치해 있는게 아닌 한 개의 구역을 차지하고 있기 때문에 드래그 했을 때 마지막 위치가 구역의 시작이 아닌 마지막이므로 1을 더 해줘야 해야 한다.
class Solution {
    public int[] solution(String[] wallpaper) {
        int[] X = new int[wallpaper.length]; 
        int[] Y = new int[wallpaper.length];

        int xMin = Integer.MAX_VALUE;
        int yMin = Integer.MAX_VALUE;
        int xMax = Integer.MIN_VALUE;
        int yMax = Integer.MIN_VALUE;

        for (int i = 0; i < wallpaper.length; i++) {
            for (int j = 0; j < wallpaper[i].length(); j++) {
                if (wallpaper[i].charAt(j) == '#') {
                    X[i] = i;
                    Y[i] = j;

                    xMin = Math.min(A, X[i]);
                    yMin = Math.min(B, Y[i]);
                    xMax = Math.max(C, X[i]+1);
                   	yMax = Math.max(D, Y[i]+1);
                }
            }
        }

        int[] answer = {xMin, yMin, xMax, yMax};
        return answer;
    }
}

 
728x90
반응형
728x90
반응형

판다스(Pandas)

 

    • 행렬 데이터를 처리하기 위한 다양한 함수를 지원하는 라이브러리
    • 파일 읽기, 저장, 행렬데이터 처리, 기본 시각화 등 지원
    • 데이터 전처리 과정에서 주로 사용됨

데이터 분석과정

 

  • 데이터 수집 > 데이터 전처리 > 데이터 가공(필요시 전처리) > 데이터 분석 탐색/시각화(필요시 전처리) > 필요시 모델 훈련(머신러닝 or 딥러닝) > 웹서비스 또는 분석 보고서
  • 책에 나온 일반적인 과정 : 데이터수집 > 전처리 > 분석 > 시각화로 설명되고 있다.
  • 분석과정은 회사에 따라 다르다.

판다스(Pandas) 설치

 

  • Anaconda Prompt에서 pip list로 pandas 설치 확인

  • jupyter notebook에서 import
import pandas as pd
  • 사용되는 데이터 파일 - 노란색 부분

 

컬럼 : 국적코드, 성별, 입국객수, 전년동기

행은 0행 부터 시작한다.

즉, 노란색 부분을 추출하려면 A열에서 C열, 1행에서 7행만 추출한다.

 

 

 

 

 

 

 

데이터 수집 시 확인 사항

 

  • 날짜 확인 : 기준일로 사용
    - 년월일시분이 나타나 있는게 좋다.|
    - 최소한 년월까지는 있어야 한다. 최소 12개의 데이터를 확보할 수 있기 때문이다.
  • 범주형 데이터 확인 : 예로 남자 또는 여자와 같은 데이터
    - 범주형 데이터가 많은 데이터가 좋다. 비교대상이 많아 지기 때문이다.
    - 비교대상이 많아지면 데이터로 보여줄 수 있는게 많아진다

데이터 읽어오기

 

  •  파일 위치 지정
    - 상대경로로 지정한다.
file_path = "./files/sample_1.xlsx"
  • 피일 데이터 추출하기
    - file_path : 파일지정(위치 포함)
    - header : 칼럼명으로 사용할 행의 위치(default - 0)
    - skipfooter : 행의 가장 밑에서부터 포함하지 않을 행의 갯수(default - 0)
    - usecols : 가지고 올 열의 범위(A분터 C까지의 열)(default - data가 있는 모든 열)
sample_1 = pd.read_excel(file_path,
                        header=1,
                        skipfooter=2,
                        usecols="A:C")

 

  • csv, excel, json많이 사용
  • csv는 순수한 text 파일로 처리 과정이 따로 안들어가서 가볍다. 즉, 용량을 더 많이 담을 수 있다.
  • excel 파일 자체에 다양한 처리 과정이 같이 들어가기 때문에 무겁다.

 

 

 

 

 

  • 데이터 조회하기
sample_1

 

  • DataFrame 정보 확인하기
    - DataFrame 타입 : 행렬을 저장 관리하는 타입
    - info()함수는 데이터의 결측치(nan,null) 데이터 확인 가능
    - RangeIndex : 전체 행(row)의 갯수 0 to 5 총 6개
    - 전체 행의 갯수와 각 컬럼의 갯수가 안맞으면 결측 데이터가 존재한다는 의미.
sample_1.info()

 

# Non-Null = not null null이 아닌 데이터의 갯수
#  Dtype = 데이터 타입
#  object 문자열
# int 숫자

0 to 5 총 6개

 

 

 

 

 

  • 데이터프레임 출력
    - 데이터 행/열이 많은 경우 -> 기본 상위 5개, 하위 5개를 추출해서 보여줌
    - 데이터 행/열의 갯수가 작으면 모두 보여줌

  • head() : 상위 데이터 조회
    - 상위 5개
    sample_1.head()​

    - 상위 1개
    sample_1.head(1)​

 

  • tail() : 마지막 데이터 조회
    - default : 5개
    - 하위 5개
    sample_1.tail()​

    - 하위 1개
    sample_1.tail(1)​

  • 기초 통계 데이터
sample_1.describe()

 

- count : 데이터 행의 갯수
- mean : 데이터 평균
- std : 표준편차
- min : 최솟값
- max : 최댓값
- 25%, 50%(중앙값), 75% : 4분위수 데이터
        → 4분위수 데이터를 이용해서 이상치(이상한) 데이터 확인

- 기초통계 데이터는 숫자값을 가지는 컬럼에 대해서만 확인

 

 

 

데이터 조회하기

 

  • key 입력하고 value 받아오기
    - 국적코드 데이터 조회하기
sample_1["국적코드"]

 

- dtype: object

  → 데이터 하나하나의 타입이 object이다.

 

 

 

 

 

 

  • 타입 확인
    - 데이터 전체의 타입
type(sample_1["국적코드"])

 

- Series : 튜플과 모양이 같다. (사용법도 동일)
- {"국적코드" : (데이터, 데이터, ...)}

 

 

 

  • 2차원 행렬 형태로 조회
sample_1[["국적코드"]]

type(sample_1[["국적코드"]])

 

- [[ ]] : 2차원의 행렬인 DataFrame 타입

 

 

 

  • 국적코드와 성별 모두 조회하기
    - 컬럼 2개이상 조회시 [[ ]] 2차원 행렬 형태로 조회해야함
sample_1[["국적코드","성별"]]

 

 

기준년월 컬럼 추가하기

 

  • 2019-11 값을 추가하기
sample_1["기준년월"] = '2019-11'
sample_1

데이터 필터링 하기

 

  • 필터링 : 조건에 맞는 값 조회하기
  • 성별 중에 여성인 데이터만 추출하기
condition = sample_1["성별"] == "여성" 
condition


  • default 값은  True
sample_1[condition == False]


  • 한 줄로 조회하기
sample_1[(sample_1["성별"] == "여성") == True]

 


  • 객체 주소 전달 방식
    - 둘다 같은 곳을 바라 본다
    - sample_1이 바뀌면 sample_2가 바뀌고 sample_2가 바뀌면 sample_1이 바뀜
sample_2 = sample_1

 

  • copy()
    - 메모리 복제방식 (신규로 동일하게 생성 됨)

    - 신규로 만들어진 메모리 주소를 받아옴 (서로 영향 안받음)
    - 주소를 넣는 방식이 아니라 메모리를 복제하는 방식
sample_2 = sample_1.copy()
728x90
반응형
728x90
반응형

📝문제

더보기

1. 문제 설명

다음은 어느 자동차 대여 회사의 자동차 대여 기록 정보를 담은CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블입니다. CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블은 아래와 같은 구조로 되어있으며, HISTORY_ID, CAR_ID, START_DATE, END_DATE는 각각 자동차 대여 기록 ID, 자동차 ID, 대여 시작일, 대여 종료일을 나타냅니다.


Column name Type Nullable 
HISTORY_ID INTEGER FALSE
CAR_ID INTEGER FALSE
START_DATE DATE FALSE
END_DATE DATE FALSE

 


2. 문제

CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 대여 시작일을 기준으로 2022년 8월부터 2022년 10월까지 총 대여 횟수가 5회 이상인 자동차들에 대해서 해당 기간 동안의 월별 자동차 ID 별 총 대여 횟수(컬럼명: RECORDS) 리스트를 출력하는 SQL문을 작성해주세요. 결과는 월을 기준으로 오름차순 정렬하고, 월이 같다면 자동차 ID를 기준으로 내림차순 정렬해주세요. 특정 월의 총 대여 횟수가 0인 경우에는 결과에서 제외해주세요.


3. 예시

예를 들어 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블이 다음과 같다면

HISTORY_ID CAR_ID START_DATE END_DATE
1 1 2022-07-27 2022-08-02
2 1 2022-08-03 2022-08-04
3 2 2022-08-05 2022-08-05
4 2 2022-08-09 2022-08-12
5 3 2022-09-16 2022-10-15
6 1 2022-08-24 2022-08-30
7 3 2022-10-16 2022-10-19
8 1 2022-09-03 2022-09-07
9 1 2022-09-18 2022-09-19
10 2 2022-09-08 2022-09-10
11 2 2022-10-16 2022-10-19
12 1 2022-09-29 2022-10-06
13 2 2022-10-30 2022-11-01
14 2 2022-11-05 2022-11-05
15 3 2022-11-11 2022-11-11

 

대여 시작일을 기준으로 총 대여 횟수가 5회 이상인 자동차는 자동차 ID가 1, 2인 자동차입니다. 월 별 자동차 ID별 총 대여 횟수를 구하고 월 오름차순, 자동차 ID 내림차순으로 정렬하면 다음과 같이 나와야 합니다.

MONTHCAR_IDRECORDS
MONTH CAR_ID RECORDS
8 2 2
8 1 2
9 2 1
9 1 3
10 2 2

✏️작성한 코드

 어려웠던 점은 조건을 줄 때 CAR_ID에 대한 조건을 주고 전체 행에 대한 조건을 따로 줘야 한다는 것이다.  먼저 대여 시작일을 기준으로 2022년 8월 부터 2022년 10월까지 총 대여 횟수가 5회 이상인 자동차들에 대한 조건을 서브쿼리로 준다. 그리고 해당 기간 동안의 월별 CAR_ID 별 총 대여 횟수 리스트를 출력한다.

 작성해놓고 왜 이렇게 적었는지 설명을 못하겠다... 헷

SELECT SUBSTRING(START_DATE,6,2) AS MONTH
		, CAR_ID
    	, COUNT(CAR_ID) AS RECORDS
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE CAR_ID IN (
    		SELECT CAR_ID 
    			FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY 
   					 WHERE SUBSTRING(START_DATE,1,7) BETWEEN '2022-08' AND '2022-10'
    		GROUP BY CAR_ID
    		HAVING COUNT(CAR_ID) >= 5)
	AND SUBSTRING(START_DATE,1,7) BETWEEN '2022-08' AND '2022-10'
GROUP BY SUBSTRING(START_DATE,6,2), CAR_ID
ORDER BY MONTH, CAR_ID DESC;

 

코드 실행 시 아래와 같은 형식으로 데이터가 출력된다.

728x90
반응형
728x90
반응형

📝 문제

더보기

1. 문제 설명

  사진들을 보며 추억에 젖어 있던 루는 사진별로 추억 점수를 매길려고 합니다. 사진 속에 나오는 인물의 그리움 점수를 모두 합산한 값이 해당 사진의 추억 점수가 됩니다. 예를 들어 사진 속 인물의 이름이 ["may", "kein", "kain"]이고 각 인물의 그리움 점수가 [5점, 10점, 1점]일 때 해당 사진의 추억 점수는 16(5 + 10 + 1)점이 됩니다. 다른 사진 속 인물의 이름이 ["kali", "mari", "don", "tony"]이고 ["kali", "mari", "don"]의 그리움 점수가 각각 [11점, 1점, 55점]]이고, "tony"는 그리움 점수가 없을 때, 이 사진의 추억 점수는 3명의 그리움 점수를 합한 67(11 + 1 + 55)점입니다.

 그리워하는 사람의 이름을 담은 문자열 배열 name, 각 사람별 그리움 점수를 담은 정수 배열 yearning, 각 사진에 찍힌 인물의 이름을 담은 이차원 문자열 배열 photo가 매개변수로 주어질 때, 사진들의 추억 점수를 photo에 주어진 순서대로 배열에 담아 return하는 solution 함수를 완성해주세요.


2. 제한사항

  • 3 ≤ name의 길이 = yearning의 길이≤ 100
    • 3 ≤ name의 원소의 길이 ≤ 7
    • name의 원소들은 알파벳 소문자로만 이루어져 있습니다.
    • name에는 중복된 값이 들어가지 않습니다.
    • 1 ≤ yearning[i] ≤ 100
    • yearning[i]는 i번째 사람의 그리움 점수입니다.
  • 3 ≤ photo의 길이 ≤ 100
    • 1 ≤ photo[i]의 길이 ≤ 100
    • 3 ≤ photo[i]의 원소(문자열)의 길이 ≤ 7
    • photo[i]의 원소들은 알파벳 소문자로만 이루어져 있습니다.
    • photo[i]의 원소들은 중복된 값이 들어가지 않습니다.

3. 입출력 예

name yearning photo result
["may", "kein", "kain", "radi"] [5, 10, 1, 3] [["may", "kein", "kain", "radi"], ["may", "kein", "brin", "deny"], ["kon", "kain", "may", "coni"]] [19, 15, 6]
["kali", "mari", "don"] [11, 1, 55] [["kali", "mari", "don"], ["pony", "tom", "teddy"], ["con", "mona", "don"]] [67, 0, 55]
["may", "kein", "kain", "radi"] [5, 10, 1, 3] [["may"], ["kein", "deny", "may"], ["kon", "coni"]] [5, 15, 0]

 


4. 입출력 예 설명

  • 입출력 예 #1

첫 번째 사진 속 "may", "kein", "kain", "radi"의 그리움 점수를 합치면 19(5 + 10 + 1 + 3)점 입니다. 두 번째 사진 속 그리워하는 사람들인 "may"와 "kein"의 그리움 점수를 합치면 15(5 + 10)점입니다. 세 번째 사진의 경우 "kain"과 "may"만 그리워하므로 둘의 그리움 점수를 합한 6(1 + 5)점이 사진의 추억 점수입니다. 따라서 [19, 15, 6]을 반환합니다.

  • 입출력 예 #2

첫 번째 사진 속 그리워하는 사람들인 "kali", "mari", "don"의 그리움 점수를 합치면 67(11 + 1 + 55)점입니다. 두 번째 사진 속엔 그리워하는 인물이 없으므로 0점입니다. 세 번째 사진 속 그리워하는 사람은 "don"만 있으므로 55점입니다. 따라서 [67, 0, 55]를 반환합니다.

✏️ 작성한 코드

 for문을 사용하여 풀었지만 데이터가 많을 경우 효율적이지 못한 코드가 될 수 있으므로 HashMap을 사용하는 것을 추천한다.

  • int[] answer = new int[photo.length]
    - int[]: 정수형 배열을 나타내는 자료형
    - new int[photo.length]: photo 배열의 길이와 같은 크기를 가진 새로운 정수형 배열을 생성
class Solution {
    public int[] solution(String[] name, int[] yearning, String[][] photo) {
        int[] answer = new int[photo.length];
        for (int i = 0; i < name.length ;i++) {
            for (int j = 0; j < photo.length; j++) {
                for (int k = 0; k < photo[j].length; k++){
                    if (photo[j][k].equals(name[i])) {
                            answer[j] += yearning[i];
                  }
                }
              }       
            }
        return answer;
   	   }
       }

✏️ 코딩짱 풀이 

HashMap 사용

import java.util.*;

class Solution {
    public int[] solution(String[] name, int[] yearning, String[][] photo) {
        int[] answer = new int[photo.length];

        HashMap<String, Integer> map = new HashMap<>();
        for(int i = 0; i < name.length; i++) {
            map.put(name[i], yearning[i]);
        }

        int sum;
        for(int i = 0; i < photo.length; i++) {
            sum = 0;
            for(int j = 0; j < photo[i].length; j++) {
                if(map.containsKey(photo[i][j])) 
                    sum += map.get(photo[i][j]);
            }   
            answer[i] = sum;
        }   
        
        return answer;
    }
}
728x90
반응형
728x90
반응형

Inner Join 복습 문제

문제 

  • 회원아이디 b001 회원의 마일리지 값보다 큰 회원정보 조회
  • 조회칼럼 : 회원아이디, 이름
-- 1
SELECT mem_id, mem_name
FROM member
WHERE mem_mileage > (SELECT mem_mileage
FROM member
WHERE mem_id ='b001') ;

-- 2
SELECT A.mem_id, A.mem_name
FROM (SELECT mem_id, mem_name
FROM member
WHERE mem_mileage > (SELECT mem_mileage FROM member WHERE mem_id ='b001')) A ;

-- 3
SELECT mem_id, mem_name
FROM member, 
(SELECT mem_mileage
FROM member
WHERE mem_id ='b001') MEM
WHERE member.mem_mileage > MEM.mem_mileage ;

 

결과는 모두 동일하다.

 

 

 

 

 

 

 

 

🎀 Self Join

    • Self Join으로 처리하기
    • 셀프조인 시 : 조건은 한쪽 m2 테이블에 적용
    • 조회 시 : m1 테이블에서 조회

Self Join 문제

문제 1번

  • Inner Join 문제 1번에 Self join을 사용해 보기
SELECT m1.mem_id, m1.mem_name
FROM member m1, member m2
WHERE m2.mem_id = 'b001'
AND m1.mem_mileage > m2.mem_mileage;

Inner Join 문제 1번과 결과가 동일하다.

 

🎀 Outer Join

  • 특정 테이블 전체에 대한 집계를 하고자 할 때 사용
  • OUTER JOIN 종류
    1. LEFT OUTER JOIN : 테이블 순서 중 왼쪽에 위치한 테이블 전체
    2. RIGHT OUTER JOIN : 테이블 순서 중 오른쪽에 위치한 테이블 전체
    3. FULL OUTER JOIN : 왼쪽, 오른쪽 전체 테이블 (Oracle DB만 사용 가능)
  • OUTER JOIN 개념
    1. Outer Join은 표준방식으로만 사용해야 하며 일반 조건은 무조건 On() 내부에 작성해야 한다
    2. 일반 조건을 where 절을 사용하면 Outer 전체 계념이 적용이 안된다
    3. Inner Join을 만족해야 한다(Inner Join 개념을 그대로 적용)
    4. Left or Right 기준으로 같으면 같은 조건대로 조회하고 다르면 null로 조회된다

Outer join 문제

문제 1번

  • 상품분류 전체에 대한 상품종류 집계
SELECT lprod_nm, COUNT(prod_lgu) AS cnt
FROM lprod 
	LEFT JOIN prod
		ON (lprod_gu = prod_lgu)
GROUP BY lprod_gu
ORDER BY cnt;


문제 2 - 1번

  • 회원별 구매금액의 총액 조회
  • 2005년 5월에 구매한 내역
  • 조회칼럼 : 회원이름, 구매금액 총액
    -- 일반 방식
    SELECT mem_name, SUM(cart_qty*prod_sale) AS total
    FROM member, prod, cart
    WHERE mem_id=cart_member
    AND cart_prod = prod_id
    AND substring(cart_no,1,6) = '200505'
    group BY mem_id, mem_name
    ORDER BY total desc;
    
    -- 표준 방식
    SELECT mem_name, SUM(cart_qty*prod_sale) AS total
    FROM member INNER join cart
    ON (mem_id=cart_member AND substring(cart_no,1,6) = '200505')
    INNER JOIN prod
    ON (cart_prod = prod_id)
    group BY cart_member
    ORDER BY total desc;​

 

찾은 행 13개

5월에 구매한 내역이 있는 고객만 조회됨

 

 

 

 

 

 

 

 


문제 2 - 2번

  • 문제 2 - 1에 이어서 회원 전체에 대해서 문제 2 - 1조건으로 조회하기
  • 총회원은 28명
SELECT mem_name, SUM(nvl(cart_qty,0)*nvl(prod_sale,0)) AS total
FROM member left join cart
ON (mem_id=cart_member)
left JOIN prod
ON (cart_prod = prod_id)
group BY mem_id, mem_name
ORDER BY total desc;

 

찾은 행 28개

구매이력이 없는 회원도 모두 조회되며

NULL값을 가지면 0으로 대체됨

 

 

 

 

 

 


문제 3 - 1번

  • 2005년도 월별 판매 현황 검색하기
  • 조회칼럼 : 판매월, 월별 총판매수량, 월별 총판매금액
SELECT substring(cart_no,1,6) AS cart_no, sum(cart_qty) AS cart_qty, sum(cart_qty*prod_sale) AS total
	FROM cart 
		left join prod
			ON (cart_prod = prod_id
					AND SUBSTRING(cart_no,1,4) = '2005')
	GROUP BY substring(cart_no,1,6);

 


문제 3 - 2번

  • 문제 3 - 1번 조건에서 1월 ~ 12월까지 모두 표현하고자 한다면?
  • 방법 1 - UNION 사용
SELECT
    months.month,
    NVL(SUM(A.cart_qty), 0) AS total_sales,
    NVL(SUM(A.cart_qty*B.prod_sale),0) AS total
FROM (
    SELECT '200501' AS month
    UNION SELECT '200502'
    UNION SELECT '200503'
    UNION SELECT '200504'
    UNION SELECT '200505'
    UNION SELECT '200506'
    UNION SELECT '200507'
    UNION SELECT '200508'
    UNION SELECT '200509'
    UNION SELECT '200510'
    UNION SELECT '200511'
    UNION SELECT '200512'
) AS months
LEFT JOIN cart A ON (SUBSTRING(A.cart_no, 1, 6) = months.month)
LEFT join prod B ON (A.cart_prod = B.prod_id)
GROUP BY months.month
ORDER BY months.month;
  • 방법 2 - 새로운 날짜 테이블 생성
-- 테이블 생성
CREATE TABLE date_mm (
	mm CHAR(2) NOT NULL
);

-- 값 입력
INSERT INTO date_mm VALUES('01');
INSERT INTO date_mm VALUES('02');
INSERT INTO date_mm VALUES('03');
INSERT INTO date_mm VALUES('04');
INSERT INTO date_mm VALUES('05');
INSERT INTO date_mm VALUES('06');
INSERT INTO date_mm VALUES('07');
INSERT INTO date_mm VALUES('08');
INSERT INTO date_mm VALUES('09');
INSERT INTO date_mm VALUES('10');
INSERT INTO date_mm VALUES('11');
INSERT INTO date_mm VALUES('12');

-- 조회 코드 작성
SELECT date_mm.mm,
	SUM(nvl(cart_qty,0)) AS total_qty,
	SUM(nvl(cart_qty*prod_sale,0)) AS total
FROM date_mm
	LEFT JOIN cart
		ON(date_mm.mm = SUBSTRING(cart_no,5,2))
	LEFT JOIN prod
		ON(cart_prod = prod_id
			AND substring(cart_no,1,4) = '2005')
GROUP BY date_mm.mm;

 

결과는 동일하다.

 

 

 

 

 

 

 

 

 


문제 4번

  • 2005년도에 대한 전체 거래처별 총매출금액 조회하기
  • 조회칼럼 : 거래처 코드, 거래처명, 총매출금액
  • 정렬 : 총매출금액 - 내림차순
SELECT buyer_id, buyer_name, SUM(nvl(cart_qty*prod_sale,0)) AS total
FROM buyer 
	LEFT join prod
		ON (buyer_id = prod_buyer)
	LEFT join cart
		ON(prod_id = cart_prod AND substring(cart_no,1,4) = '2005' )
GROUP BY buyer_id
ORDER BY total DESC;

 

찾은 행 13개

 

 

 

 

 

 

 

 

 

 

 

 

728x90
반응형

+ Recent posts