반응형

최근 프로젝트에서 JSONB 타입 컬럼(auto_generated_tags)을 사용하면서 꽤 혼란스러운 상황을 겪었습니다.
DB를 조회해 보니 일부 데이터가 null로 표시되었는데, 실제로는 JSONB 내부에 "null" 값이 들어간 경우였습니다.

  • JSON "null" → 컬럼 값은 존재하지만 내용이 JSON으로 "null"을 가지고 있음

처음엔 단순히 null로 표시된 걸 '{}' 로 변경하기 위해 아래처럼 쿼리했습니다.

UPDATE product_sample_images
SET auto_generated_tags = '{}'::jsonb
WHERE auto_generated_tags IS NULL;

하지만 결과적으로 여전히 null이 보였습니다. 왜냐하면 "null" 문자열은 IS NULL로 걸리지 않기 때문입니다.
이 문제를 해결하려면 다음과 같이 타입 캐스팅 후 체크가 필요했습니다:

UPDATE product_sample_images
SET auto_generated_tags = '{}'::jsonb
WHERE auto_generated_tags::text = 'null';


결론적으로, PostgreSQL의 NULL과 JSON의 "null"은 전혀 다르네요.

 

왜 이런 차이가 생길까? 그리고 ::는 뭘까?


PostgreSQL에서 JSONB 컬럼은 단순 문자열이 아니라 JSON 구조체를 내부적으로 파싱해 저장합니다.
이때 두 가지 상황이 발생합니다:

  1. DB 자체 NULL
    • 해당 컬럼에 값이 아예 없는 상태
    • SQL에서 IS NULL로 확인 가능
  2. JSON 내부 "null"
    • JSON 구조체의 값이 null로 저장된 상태
    • SQL 입장에서는 값이 있음 → 따라서 IS NULL에 걸리지 않음

결국 IS NULL은 DB 차원의 null만 잡을 뿐, JSON 내부 값은 따로 처리해야 합니다.

 

::는 무엇인가?


PostgreSQL에서는 :: 연산자가 타입 캐스팅(type casting) 을 의미합니다.
즉, 데이터를 다른 타입으로 변환하는 기능입니다.

예를 들어:

SELECT 123::text;         -- 숫자 123 → 문자열 '123'로 변환
SELECT '{}'::jsonb;       -- 문자열 '{}' → JSONB 객체로 변환
 

이렇게 하면 내부 구조를 문자열로 풀어서 "null"인지 확인할 수 있습니다.

JSONB 컬럼을 비교할 때도 마찬가지입니다:

 
WHERE auto_generated_tags::text = 'null';

이렇게 하면 내부 구조를 문자열로 풀어서 "null"인지 확인할 수 있습니다.

TL;DR:

- PostgreSQL에서 NULL과 JSON "null"은 다르다.
- "null" 처리는 jsonb 타입에 대해서 auto_generated_tags::text = 'null' 와 같은 타입 캐스팅이 필요하며, ::는 PostgreSQL의 타입 변환 연산자다.

반응형

'SQL' 카테고리의 다른 글

[SQL] 데이터 수정 (UPDATE, SET)  (0) 2022.02.23
[SQL] 테이블 삭제 (DELETE FROM)  (0) 2022.02.23
[SQL] 데이터 삽입 (INSERT INTO)  (0) 2022.02.22
[SQL] 하위 쿼리( Sub-query)  (0) 2022.02.22
[SQL] 테이블 행 합치기 (UNION)  (0) 2022.02.22
반응형

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

 

데이터 수정


1) 모든 행의 데이터 수정 (주의 필요)

UPDATE 테이블명
SET 열이름 = 변경할 값;

 

2) 특정한 행의 데이터 수정

UPDATE 테이블명
SET 열이름= 변경할 값
WHERE 조건절;

 

특정한 행의 데이터를 수정하는 예

 

예제


테이블: 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. 위 테이블에서 CUST_ID를 1111로 수정하는 쿼리문을 작성해보자

SSN PARTY_NM CUST_ID TEL_NO MOBILE_NO
570 AR KIM 1111 02-555-6678 010-1111-1111
691 SH HONG 1111 031-4456-9887 010-2222-2222
831 MK KANG 1111 051-999-8888 010-3333-3333
710 JH KIM 1111 032-333-1111 010-4444-4444
770 JH LEE 1111 033-111-3355 010-5555-5555
650 JH RYU 1111 02-6666-4444 010-6666-6666
820 YC JUNG 1111 02-2222-1111 010-7777-7777
891 JH JUN 1111 031-224-2222 010-8888-8888
901 SH LEE 1111 033-333-3333 010-9999-9999
더보기
UPDATE CUST_PARTY
SET CUST_ID = 1111;

 

Q2. CUST_PARTY 테이블에서 SSN열 값이 901인 고객의 MOBILE_NO를 010-9988-5555로 수정하는 쿼리문을 작성해보자

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-9988-5555
더보기
UPDATE CUST_PARTY
SET MOBILE_NO = '010-9988-5555'
WHERE SSN=901;

 

반응형
반응형

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

 

테이블 삭제


1) 테이블의 모든 열 삭제 (주의 필요)

DELETE FROM 테이블명;

 

2) 테이블의 일부인 부분 행들을 삭제 

DELETE FROM 테이블명
WHERE 조건절;

부분 행을 삭제하는 쿼리문의 예

 

예제


테이블: 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. 위 테이블에 아래의 값들을 삭제하는 쿼리문을 작성해보자

SSN: 891
PARTY_NM: JH JUN
CUST_ID: 6989
TEL_NO: 031-224-2222
MOBILE_NO: 010-8888-9999

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
901 SH LEE 5570 033-333-3333 010-9999-9999
더보기
DELETE FROM CUST_PARTY
WHERE SSN = 891;

 

 

반응형
반응형

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

 

데이터 삽입


  1. 완전한 행 삽입
INSERT INTO 테이블명
VALUES(값1, 값2, 값3);

데이터 삽입의 예

 

2. 열이름과 함께 완전한 행 삽입

INSERT INTO 테이블명(열이름1, 열이름2, 열이름3)
VALUES(값1, 값2, 값3);

열이름을 이용한 데이터 삽입의 예

 

3. 부분 행 삽입

INSERT INTO 테이블명(열이름1, 열이름3)
VALUES(값1, 값3);

 

4. SQL 쿼리문의 결과를 삽입

INSERT INTO 테이블명(열이름1, 열이름2, 열이름3)
SELECT 열이름1, 열이름2, 열이름 FROM 테이블명2 WHERE 조건절;
  • SQL 문장 결과 전체를 삽입하고 싶을 경우 VALUES 키워드 대신 하위 쿼리 사용

 

예제


테이블: 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. 위 테이블에 아래의 값들을 삽입해보자

SSN : 550
PARTY_NM: MJ YOO
CUST_ID: 8828
TEL_NO: 02-312-1111
MOBILE_NO: 010-1122-1111

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
550 MJ YOO 8828 02-312-1111 010-1122-1111
더보기

 

INSERT INTO CUST_PARTY
VALUES (550, 'MJ YOO', 8828, '02-312-1111', '010-1122-1111');

 

Q2. 위 테이블에 아래의 값들을 삽입해보자

SSN: 551
PARTY_NM: MJ YOO
CUST_ID: 8828
TEL_NO: 02-312-1111
MOBILE_NO 열에는 NULL값

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
550 MJ YOO 8828 02-312-1111 010-1122-1111
551 MJ YOO 8828 02-312-1111 NULL
더보기
INSERT INTO CUST_PARTY(SSN, PARTY_NM, CUST_ID, TEL_NO)
VALUES (551, 'MJ YOO', 8828, '02-312-1111');

 

반응형

'SQL' 카테고리의 다른 글

[SQL] 데이터 수정 (UPDATE, SET)  (0) 2022.02.23
[SQL] 테이블 삭제 (DELETE FROM)  (0) 2022.02.23
[SQL] 하위 쿼리( Sub-query)  (0) 2022.02.22
[SQL] 테이블 행 합치기 (UNION)  (0) 2022.02.22
[SQL] 테이블 합치기 (FULL OUTER JOIN)  (0) 2022.02.17
반응형

본 글은 책 "칼퇴족 김대리는 알고 나만 모르는 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단계의 쿼리문을 넣어줌

반응형
반응형

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

 

UNION 연산자는 두 개 이상의 테이블의 행을 합칠 때 사용

UNION 연산자를 활용한 테이블 행 합치기 예

 

UNION 연산자


SELECT 열이름들 FROM 테이블명1 WHERE 조건절
UNION
SELECT 열이름들 FROM 테이블명2 WHERE 조건절;

 

예제 


  • 총 3가지 테이블을 사용

1. 고객원장 테이블: CUSTOMERS

CUST_ID CUST_NM HOME_TEL
5464 JH KIM 02-333-1111
6570 LY KIM 031-111-1133
8780 AR KIM 032-998-5555
5632 KK LEE 02-6677-8888
2445 HJ WANG 055-4444-5666
3210 HH AN 031-888-0111
2596 DK SUNG 02-113-3331
더보기
CREATE TABLE CUSTOMERS
(
CUST_ID INT NOT NULL,
CUST_NM CHAR(20) NOT NULL,
HOME_TEL CHAR(20) NOT NULL,
PRIMARY KEY('CUST_ID')
);

INSERT INTO CUSTOMERS
VALUES
(5464, 'JH KIM', '02-333-1111'),
(6570, 'LY KIM', '031-111-1133'),
(8780, 'AR KIM', '032-998-5555'),
(5632, 'KK LEE', '02-6677-8888'),
(2445, 'HJ WANG', '055-4444-5666'),
(3210, 'HH AN', '031-888-0111'),
(2596, 'DK SUNG', '02-113-3331');

 

2. 주문 테이블: ORDERS

ORDER_ID CUST_ID EMP_ID ORDER_DT
10000 2596 23480 2013-12-06
10001 5464 16780 2013-11-01
10002 3210 63278 2014-03-02
10003 2445 15501 2014-02-23
10004 5632 15687 2013-11-13
더보기
CREATE TABLE ORDERS (
	ORDER_ID	INTEGER NOT NULL,
	CUST_ID	INTEGER NOT NULL,
	EMP_ID	INTEGER NOT NULL,
	ORDER_DT	TEXT NOT NULL,
	PRIMARY KEY("ORDER_ID")
);

INSERT INTO ORDERS
VALUES
(10000, 2596, 23480, '2013-12-06'),
(10001, 5464, 16780, '2013-11-01'),
(10002, 3210, 63278, '2014-03-02'),
(10003, 2445, 15501, '2014-02-23'),
(10004, 5632, 15687, '2013-11-13');

 

3. 직원 정보 테이블:테이블: EMPLOYEE

EMP_ID GRADE NM TELNO
15501 8 YK MO 5740
15687 8 SS CHANG 5547
16780 5 HY YOO 2327
63278 7 JW PARK 2304
87871 7 SW HONG 2367
23578 6 JI CHOI 4654
32480 6 JM CHA 1270
23480 5 KE LEE 5466
더보기
CREATE TABLE EMPLOYEE
(
EMP_ID INT NOT NULL,
GRADE INT NOT NULL,
NM CHAR(20) NOT NULL,
TELNO INT NOT NULL,
PRIMARY KEY('EMP_ID'));

INSERT INTO EMPLOYEE
VALUES
(15501, 8, 'YK MO', 5740),
(15687, 8, 'SS CHANG', 5547),
(16780, 5, 'HY YOO', 2327),
(63278, 7, 'JW PARK', 2304),
(87871, 7, 'SW HONG', 2367),
(23578, 6, 'JI CHOI', 4654),
(32480, 6, 'JM CHA', 1270),
(23480, 5, 'KE LEE', 5466);

 

Q1. CUSTOMERS와 EMPLOYEE 테이블을 이용하여 직원 이름과 고객 이름을 합쳐서 하나의 열로 오름차순으로 출력 

NM
AR KIM
DK SUNG
HH AN
HJ WANG
HY YOO
JH KIM
JI CHOI
JM CHA
JW PARK
KE LEE
KK LEE
LY KIM
SS CHANG
SW HONG
YK MO
더보기
SELECT CUSTOMERS.CUST_NM AS NM FROM CUSTOMERS
UNION
SELECT EMPLOYEE.NM AS NM FROM EMPLOYEE
ORDER BY 1;

 

Q2. 위 문제에서 ‘NM’이라는 별칭을 주지 않고 아래와 같이 출력한다면 결과는?

SELECT CUSTOMERS.CUST_NM FROM CUSTOMERS
UNION
SELECT EMPLOYEE.NM FROM EMPLOYEE
ORDER BY 1;
더보기
CUST_NM
AR KIM
DK SUNG
HH AN
HJ WANG
HY YOO
JH KIM
JI CHOI
JM CHA
JW PARK
KE LEE
KK LEE
LY KIM
SS CHANG
SW HONG
YK MO

 

주의할 점


1. UNION 연산자를 사용할 때 합쳐지는 SELECT 문의 열의 숫자는 반드시 동일해야 함

테이블 열의 수가 다르면 UNION 연산자 사용 불가능

  • 위와 같이 CUSTOMERS 테이블에서는 2개의 열, EMPLOYEE 테이블에서는 1개의 열을 선택하여 UNION 연산하면  에러 발생
  • Result: SELECTs to the left and right of UNION do not have the same number of result columns

 

UNION ALL 연산자


SELECT 열이름들 FROM 테이블명1 WHERE 조건절
UNION ALL
SELECT 열이름들 FROM 테이블명2 WHERE 조건절;
  • UNION과 달리, UNION ALL은 중복된 행도 모두 출력

 

예시 - CUSTOMERS와 ORDERS 테이블 이용하여 고객아이디를 합쳐서 출력

1) UNION 사용
- 중복되는 행을 출력하지 않음

SELECT CUSTOMERS.CUST_ID FROM CUSTOMERS
UNION
SELECT ORDERS.CUST_ID FROM ORDERS;
CUST_ID
2445
2596
3210
5464
5632
6570
8780

 

2) UNION ALL 사용
- 중복되는 행 모두 출력

SELECT CUSTOMERS.CUST_ID FROM CUSTOMERS
UNION ALL
SELECT ORDERS.CUST_ID FROM ORDERS;
CUST_ID
2445
2596
3210
5464
5632
6570
8780
2596
5464
3210
2445
5632
반응형
반응형

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

 

OUTER JOIN에는 크게 LEFT, RIGHT, FULL 3가지 방법이 있다. 본 글에서는 FULL OUTER JOIN을 다룬다.

FULL OUTER JOIN


  • LEFT OUTERT JOIN과 RIGHT OUTER JOIN을 합친 결과
  • OUTER는 생략 가능

FULL JOIN을 이용한 테이블 합치기

더보기
CREATE TABLE ADDR1 (
	"CUST_ID"	INT NOT NULL,
	"HOME_ADDR1"	CHAR(50) NOT NULL,
	"HOME_ADDR2"	CHAR(50) NOT NULL,
	PRIMARY KEY('CUST_ID')
);

INSERT INTO ADDR1
VALUES
(5465, '서울시 강남구 역삼동', '111-11'),
(2354, '서울시 종로구 공평동', '222-22'),
(5410, '서울시 중구 서소문동', '333-33'),
(6511, '서울시 송파구 문정동', '444-44');


CREATE TABLE MOBILE1 (
	"CUST_ID"	INT NOT NULL,
	"MOBILE_NO"	CHAR(50) NOT NULL,
	PRIMARY KEY('MOBILE_NO')
);

INSERT INTO MOBILE1
VALUES
(5465, '010-1111-1111'),
(2354, '010-2222-2222'),
(5410, '010-3333-3333'),
(5410, '010-7777-7777'),
(7979, '010-7979-7979');

 

위의 합쳐진 테이블을 만들기 위한 SQL 문장은?


SELECT ADDR1.CUST_ID, ADDR1.HOME_ADDR1, ADDR1.HOME_ADDR2,
       MOBILE1.CUST_ID AS CUST_ID2, MOBILE1.MOBILE_NO

FROM ADDR1 FULL JOIN MOBILE1
ON ADDR1.CUST_ID = MOBILE1.CUST_ID;
  • 다만 sqlite에서는 FULL JOIN을 지원하지 않음
    • Error: RIGHT and FULL OUTER JOINs are not currently supported
반응형
반응형

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

 

OUTER JOIN에는 크게 LEFT, RIGHT, FULL 3가지 방법이 있다. 본 글에서는 RIGHT OUTER JOIN을 다룬다.

RIGHT OUTER JOIN (외부 조인)


  • RIGHT OUTER JOIN이란 오른쪽 테이블을 기준으로 왼쪽 테이블을 붙이는 것을 의미
  • 'RIGHT JOIN'이라는 명령어로도 사용 가능 (OUTER 명령어 생략 가능)

RIGHT JOIN을 이용한 테이블 합치기

더보기
CREATE TABLE ADDR1 (
	"CUST_ID"	INT NOT NULL,
	"HOME_ADDR1"	CHAR(50) NOT NULL,
	"HOME_ADDR2"	CHAR(50) NOT NULL,
	PRIMARY KEY('CUST_ID')
);

INSERT INTO ADDR1
VALUES
(5465, '서울시 강남구 역삼동', '111-11'),
(2354, '서울시 종로구 공평동', '222-22'),
(5410, '서울시 중구 서소문동', '333-33'),
(6511, '서울시 송파구 문정동', '444-44');


CREATE TABLE MOBILE1 (
	"CUST_ID"	INT NOT NULL,
	"MOBILE_NO"	CHAR(50) NOT NULL,
	PRIMARY KEY('MOBILE_NO')
);

INSERT INTO MOBILE1
VALUES
(5465, '010-1111-1111'),
(2354, '010-2222-2222'),
(5410, '010-3333-3333'),
(5410, '010-7777-7777'),
(7979, '010-7979-7979');

 

특징


  1. 오른쪽 MOBILE1 테이블의 모든 값을 나타내고, 오른쪽 테이블을 기준으로 왼쪽 ADDR1 테이블이 붙음

  2. 한 개의 키 값에 두 개 이상의 값을 가지고 있으면 모든 값이 붙음
    (MOBILE1 테이블에 CUST_ID가 5410인 고객의 휴대폰 번호는 2개가 있다는 것을 알 수 있음)

  3. 오른쪽 테이블의 키 값을 기준으로 왼쪽 테이블의 키 값이 존재하지 않는다면 NULL값으로 처리
    (CUST_ID가 7979인 고객의 HOME_ADDR1, HOME_ADDR2는 NULL값으로 처리됨)

 

위의 합쳐진 테이블을 만들기 위한 SQL 문장은?


SELECT ADDR1.CUST_ID, ADDR1.HOME_ADDR1, ADDR1.HOME_ADDR2,
       MOBILE1.CUST_ID AS CUST_ID2, MOBILE1.MOBILE_NO

FROM ADDR1 RIGHT JOIN MOBILE1
ON ADDR1.CUST_ID = MOBILE1.CUST_ID;
  • 다만 sqlite에서는 RIGHT JOIN을 지원하지 않음
    • Error: RIGHT and FULL OUTER JOINs are not currently supported
  • FROM 절에서 테이블의 위치를 변경하여 LEFT JOIN을 이용해 위의 결과를 얻을 수 있음
SELECT ADDR1.CUST_ID, ADDR1.HOME_ADDR1, ADDR1.HOME_ADDR2,
       MOBILE1.CUST_ID AS CUST_ID2, MOBILE1.MOBILE_NO

FROM MOBILE1 LEFT JOIN ADDR1
ON ADDR1.CUST_ID = MOBILE1.CUST_ID;
반응형
반응형

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

 

OUTER JOIN에는 크게 LEFT, RIGHT, FULL 3가지 방법이 있다. 본 글에서는 LEFT OUTER JOIN을 다룬다.

LEFT OUTER JOIN (외부 조인)


  • LEFT OUTER JOIN이란 쪽 테이블을 기준으로 오른쪽 테이블을 붙이는 것을 의미
  • 'LEFT JOIN'이라는 명령어로 OUTER 명령어 생략 가능

LEFT JOIN을 이용한 테이블 합치기

더보기
CREATE TABLE ADDR1 (
	"CUST_ID"	INT NOT NULL,
	"HOME_ADDR1"	CHAR(50) NOT NULL,
	"HOME_ADDR2"	CHAR(50) NOT NULL,
	PRIMARY KEY('CUST_ID')
);

INSERT INTO ADDR1
VALUES
(5465, '서울시 강남구 역삼동', '111-11'),
(2354, '서울시 종로구 공평동', '222-22'),
(5410, '서울시 중구 서소문동', '333-33'),
(6511, '서울시 송파구 문정동', '444-44');


CREATE TABLE MOBILE1 (
	"CUST_ID"	INT NOT NULL,
	"MOBILE_NO"	CHAR(50) NOT NULL,
	PRIMARY KEY('MOBILE_NO')
);

INSERT INTO MOBILE1
VALUES
(5465, '010-1111-1111'),
(2354, '010-2222-2222'),
(5410, '010-3333-3333'),
(5410, '010-7777-7777'),
(7979, '010-7979-7979');

특징


  1. 왼쪽 ADDR1 테이블의 모든 값을 나타내고, 왼쪽 테이블을 기준으로 오른쪽 MOBILE1 테이블이 붙은 형태

  2. 한 개의 키 값에 두 개 이상의 값을 가지고 있으면 모든 값이 붙음
     (MOBILE1 테이블 ‘CUST_ID’ 열의 5410)

  3. 왼쪽 테이블의 키 값을 기준으로 오른쪽 테이블의 키 값이 존재하지 않는다면 NULL값 처리
    (CUST_ID가 6511인 고객의 MOBILE_NO는 NULL값 처리)

 

위의 합쳐진 테이블을 만들기 위한 SQL 문장은?


SELECT ADDR1.CUST_ID, ADDR1.HOME_ADDR1, ADDR1.HOME_ADDR2,
       MOBILE1.CUST_ID AS CUST_ID2, MOBILE1.MOBILE_NO

FROM ADDR1 LEFT JOIN MOBILE1
ON ADDR1.CUST_ID = MOBILE1.CUST_ID;
반응형
반응형

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

INNER JOIN (내부 조인)


더보기
CREATE TABLE ADDR
(
CUST_ID INT NOT NULL,
HOME_ADDR1 CHAR(50) NOT NULL,
HOME_ADDR2 CHAR(50) NOT NULL,
PRIMARY KEY('CUST_ID')
);

INSERT INTO ADDR
VALUES
(5465, '서울시 강남구 역삼동', '111-11'),
(2354, '서울시 종로구 공평', '222-22'),
(5410, '서울시 중구 서소문동', '333-33');

CREATE TABLE MOBILE
(
CUST_ID INT NOT NULL,
MOBILE_NO CHAR(50) NOT NULL,
PRIMARY KEY('CUST_ID')
);

INSERT INTO MOBILE
VALUES
(5465, '010-1111-1111'),
(2354, '010-2222-2222');

 

  • 2개의 테이블을 하나의 테이블로 합치는 방법들 중 하나
    • ADDR 테이블에서 CUST_ID, MOBILE 테이블에서 CUST_ID가 공통으로 존재하는 Key

 

SELECT ADDR.*, MOBILE.MOBILE_NO
FROM ADDR INNER JOIN MOBILE 
ON ADDR.CUST_ID = MOBILE.CUST_ID;
  • 공통된 키 열을 매칭 시킬 때 ON 키워드를 사용
  • 위 코드의 두 번째 줄에서 아래와 같이 ‘ADDR’과 ‘MOBILE’의 위치를 변경해서 작성해도 똑같이 동작함
SELECT ADDR.*, MOBILE.MOBILE_NO
FROM MOBILE INNER JOIN ADDR
ON ADDR.CUST_ID = MOBILE.CUST_ID;

 

예제 


  • 총 3가지 테이블을 사용

1. 고객원장 테이블: CUSTOMERS

CUST_ID CUST_NM HOME_TEL
5464 JH KIM 02-333-1111
6570 LY KIM 031-111-1133
8780 AR KIM 032-998-5555
5632 KK LEE 02-6677-8888
2445 HJ WANG 055-4444-5666
3210 HH AN 031-888-0111
2596 DK SUNG 02-113-3331
더보기
CREATE TABLE CUSTOMERS
(
CUST_ID INT NOT NULL,
CUST_NM CHAR(20) NOT NULL,
HOME_TEL CHAR(20) NOT NULL,
PRIMARY KEY('CUST_ID')
);

INSERT INTO CUSTOMERS
VALUES
(5464, 'JH KIM', '02-333-1111'),
(6570, 'LY KIM', '031-111-1133'),
(8780, 'AR KIM', '032-998-5555'),
(5632, 'KK LEE', '02-6677-8888'),
(2445, 'HJ WANG', '055-4444-5666'),
(3210, 'HH AN', '031-888-0111'),
(2596, 'DK SUNG', '02-113-3331');

 

2. 주문 테이블: ORDERS

ORDER_ID CUST_ID EMP_ID ORDER_DT
10000 2596 23480 2013-12-06
10001 5464 16780 2013-11-01
10002 3210 63278 2014-03-02
10003 2445 15501 2014-02-23
10004 5632 15687 2013-11-13
더보기
CREATE TABLE ORDERS (
	ORDER_ID	INTEGER NOT NULL,
	CUST_ID	INTEGER NOT NULL,
	EMP_ID	INTEGER NOT NULL,
	ORDER_DT	TEXT NOT NULL,
	PRIMARY KEY("ORDER_ID")
);

INSERT INTO ORDERS
VALUES
(10000, 2596, 23480, '2013-12-06'),
(10001, 5464, 16780, '2013-11-01'),
(10002, 3210, 63278, '2014-03-02'),
(10003, 2445, 15501, '2014-02-23'),
(10004, 5632, 15687, '2013-11-13');

 

3. 직원정보 테이블: EMPLOYEE

EMP_ID GRADE NM TELNO
15501 8 YK MO 5740
15687 8 SS CHANG 5547
16780 5 HY YOO 2327
63278 7 JW PARK 2304
87871 7 SW HONG 2367
23578 6 JI CHOI 4654
32480 6 JM CHA 1270
23480 5 KE LEE 5466
더보기
CREATE TABLE EMPLOYEE
(
EMP_ID INT NOT NULL,
GRADE INT NOT NULL,
NM CHAR(20) NOT NULL,
TELNO INT NOT NULL,
PRIMARY KEY('EMP_ID'));

INSERT INTO EMPLOYEE
VALUES
(15501, 8, 'YK MO', 5740),
(15687, 8, 'SS CHANG', 5547),
(16780, 5, 'HY YOO', 2327),
(63278, 7, 'JW PARK', 2304),
(87871, 7, 'SW HONG', 2367),
(23578, 6, 'JI CHOI', 4654),
(32480, 6, 'JM CHA', 1270),
(23480, 5, 'KE LEE', 5466);

 

Q1. CUSTOMERS와 ORDERS 테이블을 이용해 주문 이력이 있는 고객 아이디(CUST_ID), 고객 이름(CUST_NM), 주문번호(ORDER_ID) 출력

CUST_ID CUST_NM ORDER_ID
2596 DK SUNG 10000
5464 JH KIM 10001
3210 HH AN 10002
2445 HJ WANG 10003
5632 KK LEE 10004
더보기
SELECT CUSTOMERS.CUST_ID, CUST_NM, ORDER_ID 
FROM CUSTOMERS INNER JOIN ORDERS
ON CUSTOMERS.CUST_ID = ORDERS.CUST_ID;

 

Q2. 위 3개의 테이블을 이용해 주문이력이 있는 고객아이디(CUST_ID), 고객이름(CUST_NM), 주문번호(ORDER_ID), 판매직원 아이디(EMP_ID) 및 직원 이름(NM) 출력 (3개의 테이블을 합치는 문제)

CUST_ID CUST_NM ORDER_ID EMP_ID NM
2596 DK SUNG 10000 23480 KE LEE
5464 JH KIM 10001 16780 HY YOO
3210 HH AN 10002 63278 JW PARK
2445 HJ WANG 10003 15501 YK MO
5632 KK LEE 10004 15687 SS CHANG
더보기
SELECT TMP1.CUST_ID, TMP1.CUST_NM, TMP2.ORDER_ID, TMP3.EMP_ID, TMP3.NM
FROM CUSTOMERS TMP1
	 INNER JOIN ORDERS TMP2 ON TMP1.CUST_ID = TMP2.CUST_ID
	 INNER JOIN EMPLOYEE TMP3 ON TMP2.EMP_ID = TMP3.EMP_ID;

- 각 테이블에 TMP1, TMP2, TMP3 라는 별칭을 붙여서 쿼리문 작성

 

참고


  • 조인 조건을 지정하지 않은 채 두 테이블을 조인하면 곱집합이 됨
    • 위의 Q1 에서 ON 절을 제외하면 조인 조건이 지정되지 않아 두 테이블 각각의 행수를 곱한 7*5 = 35 개의 행이 출력됨
    • SELECT CUSTOMERS.CUST_ID, CUSTOMERS.CUST_NM, ORDERS.ORDER_ID
      FROM CUSTOMERS INNER JOIN ORDERS;
      
CUST_ID CUST_NM ORDER_ID
5464 JH KIM 10000
5464 JH KIM 10001
5464 JH KIM 10002
5464 JH KIM 10003
5464 JH KIM 10004
6570 LY KIM 10000
6570 LY KIM 10001
6570 LY KIM 10002
6570 LY KIM 10003
6570 LY KIM 10004
8780 AR KIM 10000
8780 AR KIM 10001
8780 AR KIM 10002
8780 AR KIM 10003
8780 AR KIM 10004
5632 KK LEE 10000
5632 KK LEE 10001
5632 KK LEE 10002
5632 KK LEE 10003
5632 KK LEE 10004
2445 HJ WANG 10000
2445 HJ WANG 10001
2445 HJ WANG 10002
2445 HJ WANG 10003
2445 HJ WANG 10004
3210 HH AN 10000
3210 HH AN 10001
3210 HH AN 10002
3210 HH AN 10003
3210 HH AN 10004
2596 DK SUNG 10000
2596 DK SUNG 10001
2596 DK SUNG 10002
2596 DK SUNG 10003
2596 DK SUNG 10004
반응형

+ Recent posts