반응형

본 글은 책 "칼퇴족 김대리는 알고 나만 모르는 SQL 기초 편"의 정리 내용입니다.

 

하위 쿼리 (Sub-query)


  • SQL 문장 안에 포함되는 또 다른 SQL 문장
  • 복잡한 SQL 문장을 간단히 만들고, 데이터 처리 속도를 빠르게 향상 시킬 수 있음

 

하위 쿼리는 크게 FROM 절과 WHERE 조건절에서 활용될 수 있음

FROM 절의 하위 쿼리


사용되는 예

  1. 조건에 맞는 대상자를 선정 후 요약
  2. 테이블 조인

 

예제


  • 2개의 테이블 사용

1. 테이블: CARD_ACCT

SSN CC_GRADE ISSUE_DT CLOSE_DT VALID_YYMM CASH_USE_FLG CC_VARIETY_CD
570 8 2012-03-26 NULL  201503 Y 11111
770 2 2011-12-22 2013-12-01 201512 NULL 44444
650 8 2013-06-08 NULL 201806 Y 11111
820 8 2013-09-28 NULL 201809 Y 22222
570 1 2009-11-17 NULL 201411 NULL 33333
770 8 2010-07-27 NULL 201407   NULL  22222
820 2 2010-09-11 NULL 201509 Y 44444
820 1 2013-11-26 NULL 201811   NULL  33333
더보기
CREATE TABLE CARD_ACCT 
(
SSN INT NOT NULL,
CC_GRADE INT NOT NULL,
ISSUE_DT CHAR(20) NOT NULL,
CLOSE_DT CHAR(20),
VALID_YYMM INT NOT NULL,
CASH_USE_FLG CHAR(5),
CC_VARIETY_CD INT NOT NULL,
PRIMARY KEY('SSN', 'CC_GRADE')
);

INSERT INTO CARD_ACCT 
VALUES
(570, 8, '2012-03-26', NULL,         201503, 'Y', 11111),
(770, 2, '2011-12-22', '2013-12-01', 201512, NULL, 44444),
(650, 8, '2013-06-08', NULL,         201806, 'Y', 11111),
(820, 8, '2013-09-28', NULL,         201809, 'Y', 22222),
(570, 1, '2009-11-17', NULL,         201411, NULL, 33333),
(770, 8, '2010-07-27', NULL,         201407, NULL, 22222),
(820, 2, '2010-09-11', NULL,         201509, 'Y', 44444),
(820, 1, '2013-11-26', NULL,         201811, NULL, 33333);

 

2. 테이블: CUST_PARTY

SSN PARTY_NM CUST_ID TEL_NO MOBILE_NO
570 AR KIM 5670 02-555-6678 010-1111-1111
691 SH HONG 2357 031-4456-9887 010-2222-2222
831 MK KANG 3977 051-999-8888 010-3333-3333
710 JH KIM 8988 032-333-1111 010-4444-4444
770 JH LEE 7702 033-111-3355 010-5555-5555
650 JH RYU 3574 02-6666-4444 010-6666-6666
820 YC JUNG 5670 02-2222-1111 010-7777-7777
891 JH JUN 6989 031-224-2222 010-8888-8888
901 SH LEE 5570 033-333-3333 010-9999-9999
더보기
CREATE TABLE CUST_PARTY
(
SSN INT NOT NULL,
PARTY_NM CHAR(20) NOT NULL,
CUST_ID INT NOT NULL,
TEL_NO CHAR(20) NOT NULL,
MOBILE_NO CHAR(20) NOT NULL,
PRIMARY KEY('SSN')
);

INSERT INTO CUST_PARTY
VALUES
(570, 'AR KIM',  5670, '02-555-6678',   '010-1111-1111'),
(691, 'SH HONG', 2357, '031-4456-9887', '010-2222-2222'),
(831, 'MK KANG', 3977, '051-999-8888',  '010-3333-3333'),
(710, 'JH KIM',  8988, '032-333-1111',  '010-4444-4444'),
(770, 'JH LEE',  7702, '033-111-3355',  '010-5555-5555'),
(650, 'JH RYU',  3574, '02-6666-4444',  '010-6666-6666'),
(820, 'YC JUNG', 5670, '02-2222-1111',  '010-7777-7777'),
(891, 'JH JUN',  6989, '031-224-2222',  '010-8888-8888'),
(901, 'SH LEE',  5570, '033-333-3333',  '010-9999-9999');

 

Q1. CARD_ACCT 테이블과 CUST_PARTY 테이블을 이용하여 현재 살아있는 신용카드(CG_GRADE가 1 혹은 2) 보유 고객과 미보유 고객의 수를 나타내면?

A1. 어렵다

SELECT CASE WHEN TMP2.SSN IS NOT NULL THEN 'O'
            ELSE 'X' END AS CC_HOLDER,			
			COUNT(CASE WHEN TMP2.SSN IS NOT NULL THEN 1 ELSE 0 END) AS CNT
            
FROM CUST_PARTY TMP1
LEFT OUTER JOIN
(SELECT DISTINCT SSN 
FROM CARD_ACCT 
WHERE CLOSE_DT IS NULL AND CC_GRADE IN (1, 2)) AS TMP2
ON TMP1.SSN = TMP2.SSN
GROUP BY 1;
  • 교재에서는 SUM(CASE WHEN TMP2.SSN IS NOT NULL THEN 1 ELSE 0 END) AS CNT 으로 표시되어 있지만 COUNT(CASE WHEN TMP2.SSN IS NOT NULL THEN 1 ELSE 0 END) AS CNT 로 변경해야 함

 

WHERE 절의 하위 쿼리


SELECT 열이름들
FROM 테이블명
WHERE 열이름 IN (SELECT 열이름 FROM 테이블명2 WHERE 조건절);
  • WHERE 조건절에서 하위 쿼리는 IN 연산자와 함께 쓰인다고 생각하면 됨

 

예시


Q1. CARD_ACCT테이블과 CUST_PARTY 테이블을 이용하여 현재 살아있는 신용카드 보유 고객의 주민등록번호, 이름, 아이디, 자택번호 및 휴대폰 번호를 출력

A1. 하위 쿼리를 사용하지 않는다면 아래와 같이 두 단계로 나누어 SQL 문장을 작성해야 함

1단계

SELECT DISTINCT SSN 
FROM CARD_ACCT 
WHERE CC_GRADE IN (1, 2) AND CLOSE_DT IS NULL;
SSN
570
820

 

2단계

SELECT * 
FROM CUST_PARTY
WHERE SSN IN ('570', '820');
SSN PARTY_NM CUST_ID TEL_NO MOBILE_NO
570 AR KIM 5670 02-555-6678 010-1111-1111
820 YC JUNG 5670 02-2222-1111 010-7777-7777

 

두 단계를 합쳐서 하위 쿼리를 사용하면 아래와 같음

SELECT * 
FROM CUST_PARTY
WHERE SSN IN (SELECT DISTINCT SSN 
FROM CARD_ACCT 
WHERE CC_GRADE IN (1, 2) AND CLOSE_DT IS NULL);

2단계에서 하드코딩된 WHERE 조건절에 1단계의 쿼리문을 넣어줌

반응형

+ Recent posts