728x90
반응형

🎄사용자  정의 함수

  • 상품테이블에서 아래 컬럼 조회하기
    - 서브쿼리 사용 (join 사용하지 않기)
    - 조회컬럼 : 상품명, 상품분류명, 상품분류코드
 SELECT prod_name
 	, (select lprod_nm FROM lprod WHERE lprod_gu = prod_lgu) AS lprod_nm
    	, prod_lgu
 FROM prod;

 

  • 상품분류명을 추출하는 함수 생성하기
    - IF문으로 NULL값 있는지 확인
    - Delimiter 뒤에는 무조건 띄어쓰기
    - 문자열이 맞지 않아서 CHARACTER SET UTF8MB4 적용
 -- 함수 구문 시작
Delimiter //

-- 사용자 정의함수
CREATE FUNCTION udfGetLprodNm(paramGu VARCHAR(10))

-- 리턴타입 정의
RETURNS VARCHAR(50) CHARACTER SET UTF8MB4

-- 함수 기능 시작
BEGIN
	
	-- 반환할 값을 저장할 변수 선언
	DECLARE result VARCHAR(50) CHARACTER SET UTF8MB4;

	-- 상품분류명을 추출하는 sql구문 작성
	SELECT lprod_nm INTO result
	FROM lprod
	WHERE lprod_gu = paramGu;
	
	-- 조회결과가 있는지 확인
	if result IS NULL then
	 SET result = 'null';
	END if;
	
	-- 반환하기
	RETURN result;
    
-- 함수 기능 종료
END //

-- 함수 전체 구문 종료
Delimiter ;

  •  생성한 함수 호출하여 처리하기
SELECT prod_name
	,defGetLprodNm(prod_lgu) AS lprod_nm
    	,prod_lgu
FROM prod;

 

위에서 서브쿼리를 사용하여 작성한 코드와 동일한 결과

찾은 행 74 개

 

 

 

 

 

 

 

 

 

사용자 함수 정의 문제

문제 1

  • 회원이름, 성별 조회하기
  • 성별은 남성, 여성으로 조회
  • 함수 이름 : udfGetMenWomen
  • udfGetMenWomen 함수 정의
    - 남성 / 여성 추출하기
Delimiter //

CREATE FUNCTION udfGetMenWomen(paramNum INT)

-- 리턴 타입 정의
RETURNS VARCHAR(4) CHARACTER SET UTF8
BEGIN
	-- 반환할 변수 선언
	DECLARE result VARCHAR(4) CHARACTER SET UTF8;
	
	-- 남여 구분을 위한 조건문 처리
	if MOD(SUBSTRING(paramNum, 1, 1), 2) = 0 THEN
		SET result = '여성';
	ELSE 
		SET result = '남성';
	END if;

	RETURN result;
	
END //

Delimiter ;

 

 

  • 생성한 함수 호출하여 처리하기
SELECT mem_name
, udfGetMenWomen(mem_regno2) AS gender
FROM member;


문제 2

  • 새로운 주문이 발생했을 때 신규주문번호를 발급하는 함수 생성하기
  • 함수이름 : udfGetNewCartNo()
  • udfGetNewCartNo 함수 정의
Delimiter //

CREATE FUNCTION udfGetNewCartNo(paramNum VARCHAR(50))

RETURNS VARCHAR(50) CHARACTER SET UTF8

BEGIN
	DECLARE result VARCHAR(50) CHARACTER SET UTF8;
	
	if SUBSTRING(paramNum,1,8) = CURDATE() then	
		set result = paramNum + 1;
	ELSE
		SET result = concat(DATE_FORMAT(CURDATE(),'%Y%m%d'),'00001');
	END if;
	
	RETURN result;

END //

Delimiter ;

 

  • 생성한 함수 호출하여 처리하기
SELECT udfGetNewCartNo(MAX(cart_no)) AS newnum
FROM cart;

 



  • udfGetNewCartNo 함수 정의 - 강사님 
--
Delimiter //

CREATE FUNCTION udfGetNewCartNo()

RETURNS VARCHAR(13) CHARACTER SET UTF8

BEGIN
	DECLARE result VARCHAR(13) CHARACTER SET UTF8;
	
	SELECT if (MAX(cart_no) IS NOT NULL,
					MAX(cart_no) + 1,
						CONCAT(replace(CURDATE(), '-', ''),
								'00001')) INTO result
													
	FROM cart
	WHERE SUBSTRING(cart_no, 1, 8) = CURDATE();
	
	RETURN result;

END //

Delimiter ;

 

  • 생성한 함수 호출하여 처리하기 - 강사님
SELECT udfGetNewCartNo();

🎄View

  •  VIEW : 가상테이블
  • 자주 사용되거나, SQL 구문이 긴 경우 조회 목적으로만 사용
  • 미리 객체화 시켜서 테이블 처럼 사용하는 방식
  • 조회만 가능하며, 입력/수정/삭제가 되지 않는다.
  • 입력/수정/삭제가 되는 경우도 있지만, VIEW 사용 목적에 맞지 않는다.
  • 구매 내역이 없는 회원 조회하기
    - 조회 컬럼 : 회원아이디, 회원이름
SELECT mem_id, mem_name
FROM member
WHERE mem_id NOT in (SELECT cart_member FROM cart);

  • 구매내역이 없는 회원 view 생성
Delimiter //

CREATE VIEW viewNoCartMember AS

-- 조회할 select문 생성
SELECT mem_id, mem_name
FROM member
WHERE mem_id NOT in (SELECT cart_member 
FROM cart)//

Delimiter ;
  • view 사용하기
    - 사용법 : 테이블과 동일
SELECT *
from viewNoCartMember;

🎄저장 프로시저(Stored Procedure; sp)

  • 프로그램 영역이 아닌, DB자체에서 SQL구문을 관리하고자 할 때 사용
  • 데이터베이스에 SQL구문을 객체화하여 호출방식으로만 사용하는 방식

  • 구매내역이 없는 회원 프로시저 생성
Delimiter //

CREATE Procedure spNoCartMember()
Begin

-- 조회할 select문 생성
SELECT mem_id, mem_name
FROM member
WHERE mem_id NOT in (SELECT cart_member 
FROM cart);

END //
Delimiter ;
  • 프로시저 호출하기
call spNoCartMember();

 

VIEW / 저장 프로시저 문제

문제 1

  • 모든 거래처별 매출 금액의 총합 조회하기
  • 단, 2005년도 주문내역
  • 조회컬럼 : 거래처 코드, 거래처명, 매출금액의 총합
  • 위 조회에 대한 select문을 view로 생성
  • 프로시저에서 위에 생성한 view를 사용하여 call
  • view이름 : viewGetBuyerAll
  • 프로시저이름 : spGetBuyerAll

  • viewGetBuyerAll VIEW 생성
Delimiter //

CREATE VIEW viewGetBuyerAll AS

	-- 조회할 select문 생성
	SELECT buyer_id
			, buyer_name
			, SUM(NVL(prod_sale*cart_qty,0)) AS total
	FROM buyer
		LEFT JOIN prod
			ON (buyer_id = prod_buyer)
		LEFT JOIN CART
			ON (prod_id = cart_prod 
					AND cart_no LIKE '2005%')
	GROUP BY buyer_id, buyer_name//

Delimiter ;

 

  • spGetBuyerAll 프로시저 생성
Delimiter //

CREATE procedure spGetBuyerAll()
begin

	-- 조회할 select문 생성
	SELECT buyer_id
			, buyer_name
			, SUM(NVL(prod_sale*cart_qty,0)) AS total
	FROM buyer
		LEFT JOIN prod
			ON (buyer_id = prod_buyer)
		LEFT JOIN CART
			ON (prod_id = cart_prod 
					AND cart_no LIKE '2005%')
	GROUP BY buyer_id, buyer_name;
	
END //	

Delimiter ;

 

  • VIEW / 프로시저 호출
SELECT *
FROM viewgetbuyerall;

CALL spGetBuyerAll();

 

 

🎄저장 모듈(Stored Module)

  •  SQL 문장을 데이터베이스 서버에 저장하여 사용자와 애플리케이션 사이에서 공유할 수 있도록 만든 일종의 SQL 컴포넌트 프로그램이며, 독립적으로 실행되거나 다른 프로그램으로 부터 실행될 수 있는 완전한 실행 프로그램이다. Oracle의 저장 모듈에는 Procedure, User Defined Function, Trigger가 있다.

  • Procedure와 Trigger의 차이점
Procedure Trigger
CREATE Proceduer 문법사용 CREATE Trigger 문법사용
EXECUTE 명령어로 실행 생성 후 자동으로 실행
COMMIT, ROLLBACK 실행 가능 COMMIT, ROLLBACK 실행 안됨

 

728x90
반응형
728x90
반응형

🎀 Union / Union All

Union

  • 조회결과와 조회결과를 행단위로 합치는 기능
  • 조회결과들 간의 칼럼의 개수는 동일해야 함
  • 조회결과들 간의 데이터 타입을 동일해야 함
  • 예시
    - 'member' 'cart'는 구분자로 쓰임
SELECT 'member', mem_id, mem_name
FROM member
UNION
SELECT 'cart', cart_member, cart_prod
FROM cart;

 

찾은 행  28개

 

 

 

 

 

 

 

 

 

UNION ALL

  • 회원 28명, 주문정보 135건 일 때 아래 코드 실행 시 결과
    UNION : 155건
    UNION ALL : 163건
SELECT 'member', mem_id, mem_name
FROM member
UNION all
SELECT 'cart', cart_member, cart_prod
FROM cart;
  • UNION : 중복제거
  • UNION ALL : 중복포함
  • MINUS : 차집합
  • INTERSECT : 교집합

Union 문제

문제 1 - 1번

SELECT mem_id, mem_name, SUM(nvl(cart_qty*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
UNION
SELECT '', '', SUM(nvl(cart_qty*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 '', '';

 

찾은 행 29개

- 그룹화 하지 않은 SUM은 전체 행의 합이 구해진다.

- Group by ' ', ' ' 는 아무 의미가 없지만 빈 문자열로 컬럼을 지정하면 오류가 나기 때문에 문법상 적어준 것이다.

 

 

 

 

 

 

 

 


문제 1 - 2번

  • Union 문제 1 - 1번 에서 총 구매금액 순을 내림차순으로 정렬
  • 단, 총 구매금액의 총합은 마지막 행에 위치
SELECT A.mem_id, A.mem_name, A.total
FROM 
(SELECT mem_id, mem_name, SUM(nvl(cart_qty*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
ORDER BY total DESC) A
UNION
SELECT '', '', SUM(nvl(cart_qty*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 '', '';

 

 

 

 

 

 

 

 

 

 

 

 

 

🎀 Exists / Not Exists

Exists

  • 조회결과가 1건이라도 있으면 true, 0건이면 false
  • 서브쿼리를 적용(다중컬럼의 다중행 모두 가능)
  • 예시
    - 구매내역이 있는 회원만 조회
    - 아래 쿼리 실행시 회원 28명 중 19명이 조회 된다.

    SELECT mem_id, mem_name
    FROM member
    WHERE EXISTS(SELECT *
    FROM cart
    WHERE cart_member = mem_id);​

Not Exists

  • 예시
    -
    구매 (주문) 내역이 없는 회원만 조회
    - 아래 쿼리 실행시 회원 28명 중 9명이 조회 된다.
SELECT mem_id, mem_name
FROM member
WHERE NOT EXISTS (SELECT * FROM cart WHERE mem_id = cart_member);

 

Exists / Not Exists 문제

문제 1번

  • 2005년도 구매내역이 있는 회원 조회하기
  • 단, 구매내역이 있는 회원의 총구매금액이 3천만원 이상인 데이터에 대해서만 조회
  • 조회컬럼 : 회원아이디, 회원이름, 마일리지
  • 방법 1 - Exists 사용
SELECT mem_id, mem_name, mem_mileage
FROM member
WHERE EXISTS (
		SELECT SUM(cart_qty*prod_sale)
			FROM cart, prod
			WHERE cart_member = mem_id
				AND cart_prod = prod_id
				AND left(cart_no,4) = '2005'
		HAVING SUM(cart_qty*prod_sale) >= 30000000);
  • 방법 2 - Inline View 사용
SELECT A.mem_id, A.mem_name, A.mem_mileage
FROM(
	SELECT mem_id, mem_name, mem_mileage, SUM(nvl(cart_qty*prod_sale,0)) AS total
		FROM member 
        	LEFT JOIN cart
				ON ( mem_id = cart_member AND left(cart_no,4) = '2005')
			LEFT JOIN prod
				ON(cart_prod = prod_id)
		GROUP BY mem_id) A
WHERE A.total >= 30000000;

 

결과는 동일하다.

 

 

 

🎀 UPDATE

  • 데이터 수정하기
  • UPDATE 할 땐 수정하려는 값이 문제에서 제시한 수정 대상이 맞는지  SELECT ~ WHERE 절로 확인하기
  • 수정 및 삭제 시 기준 컬럼은 PK값을 기준으로 행을 조건 처리 해야 함
  • 예시 1
    - 회원아이디 a001, b001인 회원의 마일리지 값을 2로 수정
UPDATE member set mem_mileage = 2
WHERE mem_id IN ('a001','b001') ;
  • 예시 2
    - 구매내역이 있는 회원의 마일리지 값을 3으로 일괄 수정처리하기
UPDATE member SET mem_mileage =3
WHERE EXISTS(SELECT *
FROM cart
WHERE cart_member = mem_id);

 

UPDATE 문제

문제 1

  • Exists 문제 1번 조건에 만족하는 회원에 대해서 마일리지 값을 1000점 부여하기
  • 방법 1 - Exists 사용
UPDATE member SET mem_mileage = 1000
WHERE EXISTS (
			SELECT SUM(cart_qty*prod_sale)
				FROM cart, prod
					WHERE cart_member = mem_id
						AND cart_prod = prod_id
						AND left(cart_no,4) = '2005'
					HAVING SUM(cart_qty*prod_sale) >= 30000000);
  • 방법 2 - Inline View 사용
UPDATE member SET mem_mileage = (mem_mileage + 1000)
	WHERE mem_id IN(
		SELECT A.mem_id
		FROM (
			SELECT mem_id, mem_name, mem_mileage, SUM(nvl(cart_qty*prod_sale,0)) AS total
			FROM member 
				LEFT JOIN cart
					ON ( mem_id = cart_member AND left(cart_no,4) = '2005')
				LEFT JOIN prod
					ON(cart_prod = prod_id)
			GROUP BY mem_id) A
	WHERE A.total >= 30000000);
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
반응형
728x90
반응형

문제

  • 가장 최근에 입고된 상품의 상품명, 거래처명
  • 가장 최근에 입고된 상품을 가장 많이 구매한 회원의 아이디, 이름, 마일리지, 해당 상품 구매수량, 회원등급 구하기
  • 조회 컬럼 : 상품명, 거래처명, 회원아이디, 회원이름, 마일리지, 해당 상품 구매수량, 회원 등급
  • 등급 조건
마일리지 등급
~ 999 아이언
1000 ~ 1999 브론즈
2000 ~ 2999 실버
3000 ~ 3999 골드
4000 ~ 4999 플래티넘
5000 ~  다이아
  • ERD

작성한 코드

코드 1

SELECT  AA.prod_name, AA.buyer_name, AA.mem_id, AA.mem_name, AA.mem_mileage, AA.cart_qty,
(CASE
        WHEN AA.mem_mileage BETWEEN 1000 AND 2000 THEN '브론즈'
        WHEN AA.mem_mileage BETWEEN 2000 AND 3000 THEN '실버'
        WHEN AA.mem_mileage BETWEEN 3000 AND 4000 THEN '골드'
        WHEN AA.mem_mileage BETWEEN 4000 AND 5000 THEN '플래티넘'
        WHEN AA.mem_mileage >= 5000 THEN '다이아'
    	ELSE '아이언'
	 END) AS grade 
FROM (
	SELECT prod_name, buyer_name, mem_id, mem_name, mem_mileage, cart_qty, cart_prod
   	FROM member, cart, prod, buyer
    		WHERE mem_id = cart_member
            AND cart_prod = prod_id
            AND prod_buyer = buyer_id 
      ) AA,
     (
	SELECT cart_prod, MAX(cart_qty) AS cart_qty
		FROM cart
    		WHERE cart_prod IN (
           				 SELECT B.buy_prod
           					 FROM (SELECT MAX(buy_date) AS max_date
                  					FROM buyprod) A,
                 					(SELECT buy_prod, buy_date
                  					FROM buyprod) B
            					WHERE A.max_date = B.buy_date)
    			GROUP BY cart_prod ) BB
	WHERE AA.cart_prod = BB.cart_prod 
      AND AA.cart_qty = BB.cart_qty
	ORDER BY prod_name;

 

 

코드 2

출처 미니 조코딩 님

https://sujakjil.tistory.com/54

SELECT prod_name ,buyer_name ,mem_id , mem_name , mem_mileage , cart_qty ,
      (case 
      when mem_mileage BETWEEN 1000 AND 1999 then '브론즈'
      when mem_mileage BETWEEN 2000 AND 2999 then '실버'
      when mem_mileage BETWEEN 3000 AND 3999 then '골드'
      when mem_mileage BETWEEN 4000 AND 4999 then '플래티넘'
      ELSE '다이아' 
      END) AS 'grade'
FROM member , cart , prod , buyer
WHERE prod_id = cart_prod
AND mem_id = cart_member
AND prod_buyer = buyer_id
AND prod_id IN (SELECT prod_id FROM buyprod , prod 
               WHERE prod_id = buy_prod
               AND buy_date = (SELECT MAX(buy_date)
               FROM buyprod))
AND cart_qty in (SELECT  MAX(cart_qty)
FROM cart , prod
WHERE cart_prod = prod_id
and prod_id IN (SELECT prod_id FROM buyprod , prod 
               WHERE prod_id = buy_prod
               AND buy_date = (SELECT MAX(buy_date)
               FROM buyprod))
GROUP BY prod_id);

결과

728x90
반응형
728x90
반응형

📝문제

더보기

1. 문제 설명

 어느 학교에 페인트가 칠해진 길이가 n미터인 벽이 있습니다. 벽에 동아리 · 학회 홍보나 회사 채용 공고 포스터 등을 게시하기 위해 테이프로 붙였다가 철거할 때 떼는 일이 많고 그 과정에서 페인트가 벗겨지곤 합니다. 페인트가 벗겨진 벽이 보기 흉해져 학교는 벽에 페인트를 덧칠하기로 했습니다.

 넓은 벽 전체에 페인트를 새로 칠하는 대신, 구역을 나누어 일부만 페인트를 새로 칠 함으로써 예산을 아끼려 합니다. 이를 위해 벽을 1미터 길이의 구역 n개로 나누고, 각 구역에 왼쪽부터 순서대로 1번부터 n번까지 번호를 붙였습니다. 그리고 페인트를 다시 칠해야 할 구역들을 정했습니다.

 벽에 페인트를 칠하는 롤러의 길이는 m미터이고, 롤러로 벽에 페인트를 한 번 칠하는 규칙은 다음과 같습니다.

  • 롤러가 벽에서 벗어나면 안 됩니다.
  • 구역의 일부분만 포함되도록 칠하면 안 됩니다.

 즉, 롤러의 좌우측 끝을 구역의 경계선 혹은 벽의 좌우측 끝부분에 맞춘 후 롤러를 위아래로 움직이면서 벽을 칠합니다. 현재 페인트를 칠하는 구역들을 완전히 칠한 후 벽에서 롤러를 떼며, 이를 벽을 한 번 칠했다고 정의합니다.

 한 구역에 페인트를 여러 번 칠해도 되고 다시 칠해야 할 구역이 아닌 곳에 페인트를 칠해도 되지만 다시 칠하기로 정한 구역은 적어도 한 번 페인트칠을 해야 합니다. 예산을 아끼기 위해 다시 칠할 구역을 정했듯 마찬가지로 롤러로 페인트칠을 하는 횟수를 최소화하려고 합니다.

 정수 nm과 다시 페인트를 칠하기로 정한 구역들의 번호가 담긴 정수 배열 section이 매개변수로 주어질 때 롤러로 페인트칠해야 하는 최소 횟수를 return 하는 solution 함수를 작성해 주세요.

 

2. 제한사항

  • 1 ≤ m ≤ n ≤ 100,000
  • 1 ≤ section의 길이 ≤ n
    • 1 ≤ section의 원소 ≤ n
    • section의 원소는 페인트를 다시 칠해야 하는 구역의 번호입니다.
    • section에서 같은 원소가 두 번 이상 나타나지 않습니다.
    • section의 원소는 오름차순으로 정렬되어 있습니다.

3. 입출력 예

n m section result
8 4 [2, 3, 6] 2
5 4 [1, 3] 1
4 1 [1, 2, 3, 4] 4

 


4. 입출력 예 설명

  • 입출력 예 #1
     예제 1번은 2, 3, 6번 영역에 페인트를 다시 칠해야 합니다. 롤러의 길이가 4미터이므로 한 번의 페인트칠에 연속된 4개의 구역을 칠할 수 있습니다. 처음에 3, 4, 5, 6번 영역에 페인트칠을 하면 칠해야 할 곳으로 2번 구역만 남고 1, 2, 3, 4번 구역에 페인트칠을 하면 2번 만에 다시 칠해야 할 곳에 모두 페인트칠을 할 수 있습니다.2번보다 적은 횟수로 2, 3, 6번 영역에 페인트를 덧칠하는 방법은 없습니다. 따라서 최소 횟수인 2를 return 합니다.
  • 입출력 예 #2
     예제 2번은 1, 3번 영역에 페인트를 다시 칠해야 합니다. 롤러의 길이가 4미터이므로 한 번의 페인트칠에 연속된 4개의 구역을 칠할 수 있고 1, 2, 3, 4번 영역에 페인트칠을 하면 한 번에 1, 3번 영역을 모두 칠할 수 있습니다. 따라서 최소 횟수인 1을 return 합니다.

  • 입출력 예 #3 
     예제 3번은 모든 구역에 페인트칠을 해야 합니다. 롤러의 길이가 1미터이므로 한 번에 한 구역밖에 칠할 수 없습니다. 구역이 4개이므로 각 구역을 한 번씩만 칠하는 4번이 최소 횟수가 됩니다. 따라서 4를 return 합니다

✏️작성한 코드

Java

class Solution {
    public int solution(int n, int m, int[] section) {
        int answer = 1;
        int start = section[0];
        for (int i = 0; i < section.length; i++) {
                if(section[i] > start + m - 1) {
                    answer += 1;
                    start = section[i];
                }
            }
        return answer;
    }
}

✒️ 코딩짱 풀이

미니 조코딩 님 - Python

https://sujakjil.tistory.com/53

def solution(n, m, section):
    a = section[0]
    cnt = 1
    for i,s in enumerate(section) :
        if s > a+m-1:
            cnt += 1
            if i != len(section)-1:
                a = section[i]
    return cnt

 

cow1 님 - Python

https://codingwithyou.tistory.com/

def solution(n, m, section):
    answer = 1
    start = section[0]
    for i in section:
        
        # start = section[i][j]
        if i > start+(m - 1):
            answer += 1
            start = i
    return answer
728x90
반응형

+ Recent posts