1. 코딩 환경 설정
  2. 데이타베이스와 테이블 생성
  3. SELECT로 시작하는 데이터 탐험
  4. 데이터 타입 이해
  5. 데이터 가져오고 내보내기
  6. SQL을 사용한 기본 수학 및 통계
  7. 관계형 데이터베이스에서 테이블 조인

이 책에 대하여

  1. SQL은 무엇인가?
  2. 왜 SQL을 사용해야 할까?
  3. 엑셀은 시트 하나당 최대 1,048,576개의 행을 생성할 수 있습니다.
  4. 액세스는 데이터베이스 코개가 2GB로 제한되어 있고 테이블당 열을 255개까지만 생성할 수 있습니다.

1. 코딩 환경 설정

목차로 돌아가기


2. 데이타베이스와 테이블 생성

  1. 테이블 이해
  2. pgAdmin에서 SQL 실행

테이블 생성

CREATE DATABASE dju;
CREATE TABLE teachers (
  id bigserial, -- bigserial은 자동으로 증가하는 숫자를 생성합니다 (PostgreSQL에서만 사용 가능)
  first_name varchar(25), -- varchar는 가변 길이 문자열을 저장합니다 (예: 'Aaron')
  last_name varchar(50),
  school varchar(50),
  hire_date date, -- date는 날짜를 저장합니다 (예: YYYY-MM-DD)
  salary numeric -- numeric은 숫자를 저장합니다 (예: 123456.78)
);

테이블에 행 삽입

INSERT INTO teachers (first_name, last_name, school, hire_date, salary)
VALUES ('Aaron', 'Snowberger', 'Daejeon University', '2023-09-01', 10000),
        ('John', 'Doe', 'Daejeon University', '2023-09-01', 10000),
        ('Jane', 'Doe', 'Daejeon University', '2023-09-01', 10000);

테이블 데이터 보기

TABLE teachers; -- 테이블의 모든 열을 보여줍니다 (1번째 방법)

SELECT * FROM teachers; -- 테이블의 모든 열을 보여줍니다 (2번째 방법)

목차로 돌아가기


3. SELECT로 시작하는 데이터 탐험

SELECT

SELECT * FROM teachers; -- 테이블의 모든 열을 보여줍니다

WHERE

SELECT * FROM teachers
WHERE first_name = 'Aaron'; -- first_name이 'Aaron'인 행만 보여줍니다

AND

SELECT * FROM teachers
WHERE first_name = 'Aaron' AND last_name = 'Snowberger'; -- first_name이 'Aaron'이고 last_name이 'Snowberger'인 행만 보여줍니다

OR

SELECT * FROM teachers
WHERE first_name = 'Aaron' OR first_name = 'John'; -- first_name이 'Aaron'이거나 'John'인 행만 보여줍니다

IN

SELECT * FROM teachers
WHERE first_name IN ('Aaron', 'John'); -- first_name이 'Aaron'이거나 'John'인 행만 보여줍니다

NOT

SELECT * FROM teachers
WHERE first_name NOT IN ('Aaron', 'John'); -- first_name이 'Aaron'이거나 'John'이 아닌 행만 보여줍니다

BETWEEN

SELECT * FROM teachers
WHERE hire_date BETWEEN '2023-09-01' AND '2023-09-30'; -- hire_date가 '2023-09-01'과 '2023-09-30' 사이인 행만 보여줍니다

LIKE

SELECT * FROM teachers
WHERE first_name LIKE 'A%'; -- first_name이 'A'로 시작하는 행만 보여줍니다

ILIKE

SELECT * FROM teachers
WHERE first_name ILIKE 'a%'; -- first_name이 'a'로 시작하는 행만 보여줍니다 (대소문자 구분 없음)

ORDER BY

SELECT * FROM teachers
ORDER BY last_name; -- last_name을 오름차순으로 정렬합니다
SELECT * FROM teachers
ORDER BY last_name DESC; -- last_name을 내림차순으로 정렬합니다

LIMIT

SELECT * FROM teachers
LIMIT 2; -- 행을 2개만 보여줍니다

DISTINCT

SELECT DISTINCT school FROM teachers; -- school 열의 중복을 제거합니다

COUNT

SELECT COUNT(*) FROM teachers; -- 행의 개수를 세어줍니다

SUM

SELECT SUM(salary) FROM teachers; -- salary 열의 합을 구합니다

AVG

SELECT AVG(salary) FROM teachers; -- salary 열의 평균을 구합니다

MIN

SELECT MIN(salary) FROM teachers; -- salary 열의 최솟값을 구합니다

MAX

SELECT MAX(salary) FROM teachers; -- salary 열의 최댓값을 구합니다

GROUP BY

SELECT school, COUNT(*) FROM teachers
GROUP BY school; -- school 열의 중복을 제거하고 행의 개수를 세어줍니다

HAVING

SELECT school, COUNT(*) FROM teachers
GROUP BY school
HAVING COUNT(*) > 1; -- school 열의 중복을 제거하고 행의 개수가 1보다 큰 행만 보여줍니다

AS

SELECT school, COUNT(*) AS count FROM teachers
GROUP BY school
HAVING COUNT(*) > 1; -- school 열의 중복을 제거하고 행의 개수가 1보다 큰 행만 보여줍니다

목차로 돌아가기


4. 데이터 타입 이해

데이터 타입

문자열

  • char(n) (입력한 n 에 따라 길)
  • varchar(n) (최대 길이가 n)
  • text (길이 제한이 없는 가변 길 (1GB 입니다))

숫자

정수

  • smallint (2바이트)
  • integer (4바이트)
  • bigint (8바이트)

실수

  • numeric(10, 2) (고정 소수점) - fixed point - 10자리 숫자 중 소수점 이하 2자리까지 정밀도
  • real (부동 소수점) - single precision (소수점 이하 6자리까지 정밀도)
  • double precision (부동 소수점) - double precision (소수점 이하 15자리까지 정밀도)

자동 증가

  • smallserial (2바이트) PostgreSQL에서만 사용 가능
  • serial (4바이트) PostgreSQL에서만 사용 가능
  • bigserial (8바이트) PostgreSQL에서만 사용 가능
  • id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY; 다른 데이터베이스에서는 이렇게 사용합니다

날짜

  • date (YYYY-MM-DD) (예: ‘2023-09-01’) = 4바이트
  • time (HH:MM:SS) (예: ‘12:30:00’) = 8바이트
  • timestamp (YYYY-MM-DD HH:MM:SS) (예: ‘2023-09-01 12:30:00’) = 8바이트
  • interval (예: ‘1 day’) = 16바이트
  • 불리언

JSON

  • json (JSON 데이터) = 키/값 쌍과 값 목록의 컬렉션으로 정보를 구성하는 데이터 형식
  • jsonb (JSON 데이터) = json과 동일하지만, 데이터가 정렬되어 있습니다 (인덱성을 지원하므로 처리 속도가 빠릅니다)

다른 타입

  • boolean (true/false)
  • enum (열거형)
  • uuid (UUID)
  • xml (XML 데이터)
  • range (범위)
  • geomtric (기하학)
  • text search (텍스트 검색)
  • cidr (IPv4/IPv6 네트워크 주소)
  • inet (IPv4/IPv6 호스트 주소)
  • macaddr (MAC 주소)
  • bit (비트열)
  • bit varying (가변 비트열)
  • NULL (데이터가 없음)

데이터 타입 변환

SELECT CAST('2023-09-01' AS date); -- 문자열을 날짜로 변환합니다
SELECT CAST('2023-09-01' AS date) + 1 AS tomorrow; -- 날짜에 1을 더하고 열의 이름을 'tomorrow'로 지정합니다
SELECT timestamp_column, CAST(timestamp_column AS varchar(10))
FROM data_time_types; -- timestamp_column 열을 문자열로 변환합니다

SELECT timestamp_column, timestamp_column::varchar(10)
FROM data_time_types; -- 위와 동일한 결과를 보여줍니다

목차로 돌아가기


5. 데이터 가져오고 내보내기

데이터 가져오기

CREATE TABLE teachers (
  id bigserial,
  first_name varchar(25),
  last_name varchar(50),
  school varchar(50),
  hire_date date,
  salary numeric
);

COPY teachers (first_name, last_name, school, hire_date, salary)
FROM '/Users/aaronkr/Desktop/teachers.csv'
WITH (FORMAT CSV, HEADER); -- CSV 파일을 테이블에 삽입합니다

삭제하기

DELETE FROM teachers; -- 테이블의 모든 행을 삭제합니다

DELETE FROM teachers
WHERE id = 1; -- id가 1인 행을 삭제합니다

데이터 가져오기 및 WHERE

COPY teachers (first_name, last_name, school, hire_date, salary)
FROM '/Users/aaronkr/Desktop/teachers.csv'
WITH (FORMAT CSV, HEADER)
WHERE salary > 10000; -- CSV 파일에서 salary가 10000보다 큰 행만 테이블에 삽입합니다

감시 테이블 (안 배웠지만 유용합니다)

 CREATE TEMPORARY TABLE supervisor_salaries_temp
    (LIKE supervisor_salaries INCLUDING ALL);

COPY supervisor_salaries_temp (town, supervisor, salary)
FROM 'C:\YourDirectory\supervisor_salaries.csv'
WITH (FORMAT CSV, HEADER);

INSERT INTO supervisor_salaries (town, county, supervisor, salary)
SELECT town, 'Mills', supervisor, salary
FROM supervisor_salaries_temp;

DROP TABLE supervisor_salaries_temp;

데이터 내보내기

COPY teachers (first_name, last_name, school, hire_date, salary)
TO '/Users/aaronkr/Desktop/teachers.txt'
WITH (FORMAT CSV, HEADER, DELIMITER '|'); -- 테이블의 모든 행을 CSV 파일로 내보냅니다

데이터 내보내기 및 WHERE

COPY teachers (first_name, last_name, school, hire_date, salary)
TO '/Users/aaronkr/Desktop/teachers.txt'
WITH (FORMAT CSV, HEADER, DELIMITER '|')
WHERE salary > 10000; -- 테이블에서 salary가 10000보다 큰 행만 CSV 파일로 내보냅니다

데이터 내보내기 및 SELECT

COPY (
  SELECT first_name, last_name
  FROM teachers
  WHERE first_name ILIKE 'a%'
  )
TO '/Users/aaronkr/Desktop/teachers.txt'
WITH (FORMAT CSV, HEADER, DELIMITER '|'); -- 테이블에서 salary가 10000보다 큰 행의 first_name과 last_name 열만 CSV 파일로 내보냅니다

목차로 돌아가기


6. SQL을 사용한 기본 수학 및 통계

기본 수학

연산

  • + (더하기)
  • - (빼기)
  • * (곱하기)
  • / (나누기)
  • % (나머지)
  • ^ (거듭제곱)
  • |/ (제곱근)
  • ||/ (큐브 루트)
  • || (절대값)
  • ! (팩토리얼)
SELECT 1 + 1; -- 2
SELECT 1 - 1; -- 0
SELECT 2 * 2; -- 4
SELECT 4 / 2; -- 2
SELECT 4 % 2; -- 0
SELECT 2 ^ 3; -- 8
SELECT 2 ^ 0.5; -- 1.4142135623730951
SELECT 2 ^ -1; -- 0.5
SELECT 2 ^ 0; -- 1
SELECT 2 ^ NULL; -- NULL
SELECT 2 ^ 3 ^ 2; -- 512
SELECT (2 ^ 3) ^ 2; -- 64
SELECT 2 ^ (3 ^ 2); -- 512
SELECT 2 ^ 3 * 2; -- 16
SELECT 11 / 6;
SELECT 11 % 6;
SELECT 11.0 / 6;
SELECT CAST(11 AS numeric(3,1)) / 6;
SELECT 3 ^ 4;
SELECT |/ 10;
SELECT sqrt(10);
SELECT ||/ 10;
SELECT factorial(4);
SELECT 4 !;

테이블에서 하는 수학

SELECT salary * 2 AS double_salary FROM teachers; -- salary 열의 값에 2를 곱하고 열의 이름을 'double_salary'로 지정합니다
SELECT county_name AS county,
       state_name AS state,
       area_water::numeric / (area_land + area_water) * 100 AS pct_water
FROM us_counties_pop_est_2019
ORDER BY pct_water DESC;

통계

Tracking Percent Change / 퍼센트 변화 추적

(new_number - old_number) / old_number * 100

CREATE TABLE percent_change (
  department text,
  spend_2019 numeric(10,2),
  spend_2022 numeric(10,2)
);

INSERT INTO percent_change
VALUES
  ('Assessor', 178556, 179500),
  ('Building', 250000, 289000),
  ('Clerk', 451980, 650000),
  ('Library', 87777, 90001),
  ('Parks', 250000, 223000),
  ('Water', 199000, 195000);

SELECT department,
      spend_2019,
      spend_2022,
      round( (spend_2022 - spend_2019) /
                    spend_2019 * 100, 1) AS pct_change
FROM percent_change;

SUM / 합계

SELECT SUM(salary) FROM teachers; -- salary 열의 합을 구합니다

평균

SELECT AVG(salary) FROM teachers; -- salary 열의 평균을 구합니다

중간값

SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) AS median_salary
FROM teachers; -- salary 열의 중간값을 구합니다

Finding Other Quantiles with Percentile Functions / 백분위수 함수를 사용하여 다른 백분위수 찾기

SELECT percentile_cont(ARRAY[.25,.5,.75])
       WITHIN GROUP (ORDER BY salary) AS quartiles
FROM teachers;

SELECT unnest(
    percentile_cont(ARRAY[.25,.5,.75])
    WITHIN GROUP (ORDER BY salary)
  ) AS quartiles
FROM teachers;

Finding the mode /


SELECT mode() WITHIN GROUP (ORDER BY births_2019)
FROM us_counties_pop_est_2019;

최빈값

SELECT salary, COUNT(*) AS count
FROM teachers
GROUP BY salary
ORDER BY count DESC
LIMIT 1; -- salary 열의 최빈값을 구합니다

표준편차

SELECT STDDEV(salary) FROM teachers; -- salary 열의 표준편차를 구합니다

분산

SELECT VARIANCE(salary) FROM teachers; -- salary 열의 분산을 구합니다

최솟값

SELECT MIN(salary) FROM teachers; -- salary 열의 최솟값을 구합니다

최댓값

SELECT MAX(salary) FROM teachers; -- salary 열의 최댓값을 구합니다

목차로 돌아가기


7. 관계형 데이터베이스에서 테이블 조인

조인

SELECT *
FROM table_a JOIN table_b
ON table_a.key_column = table_b.foreign_key_column; -- table_a 테이블과 table_b 테이블을 조인합니다
SELECT *
FROM teachers
JOIN departments ON teachers.department_id = departments.id; -- teachers 테이블과 departments 테이블을 조인합니다
SELECT *
FROM teachers
JOIN departments ON teachers.department_id = departments.id
WHERE departments.name = 'Assessor'; -- teachers 테이블과 departments 테이블을 조인하고 departments 테이블의 name 열이 'Assessor'인 행만 보여줍니다

예제

CREATE TABLE departments (
    dept_id integer,
    dept text,
    city text,
    CONSTRAINT dept_key PRIMARY KEY (dept_id),
    CONSTRAINT dept_city_unique UNIQUE (dept, city)
);

CREATE TABLE employees (
    emp_id integer,
    first_name text,
    last_name text,
    salary numeric(10,2),
    dept_id integer REFERENCES departments (dept_id),
    CONSTRAINT emp_key PRIMARY KEY (emp_id)
);

INSERT INTO departments
VALUES
    (1, 'Tax', 'Atlanta'),
    (2, 'IT', 'Boston');

INSERT INTO employees
VALUES
    (1, 'Julia', 'Reyes', 115300, 1),
    (2, 'Janet', 'King', 98000, 1),
    (3, 'Arthur', 'Pappas', 72700, 2),
    (4, 'Michael', 'Taylor', 89500, 2);

SELECT *
FROM employees
JOIN departments ON employees.dept_id = departments.dept_id
ORDER BY employees.dept_id;

JOIN 종류

  • INNER JOIN (두 테이블의 공통된 행만 보여줍니다)
  • LEFT JOIN (왼쪽 테이블의 모든 행을 보여줍니다)
  • RIGHT JOIN (오른쪽 테이블의 모든 행을 보여줍니다)
  • FULL OUTER JOIN (두 테이블의 모든 행을 보여줍니다)
  • CROSS JOIN (두 테이블의 모든 행을 보여줍니다)

예제


CREATE TABLE district_2020 (
  id integer CONSTRAINT id_key_2020 PRIMARY KEY,
  school_2020 text
);

CREATE TABLE district_2035 (
  id integer CONSTRAINT id_key_2035 PRIMARY KEY,
  school_2035 text
);

INSERT INTO district_2020 VALUES
  (1, 'Oak Street School'),
  (2, 'Roosevelt High School'),
  (5, 'Dover Middle School'),
  (6, 'Webutuck High School');

INSERT INTO district_2035 VALUES
  (1, 'Oak Street School'),
  (2, 'Roosevelt High School'),
  (3, 'Morrison Elementary'),
  (4, 'Chase Magnet Academy'),
  (6, 'Webutuck High School');

INNER JOIN

SELECT *
FROM district_2020
INNER JOIN district_2035
ON district_2020.id = district_2035.id; -- 두 테이블의 공통된 행만 보여줍니다

LEFT JOIN

SELECT *
FROM district_2020
LEFT JOIN district_2035
ON district_2020.id = district_2035.id; -- 왼쪽 테이블의 모든 행을 보여줍니다

RIGHT JOIN

SELECT *
FROM district_2020
RIGHT JOIN district_2035
ON district_2020.id = district_2035.id; -- 오른쪽 테이블의 모든 행을 보여줍니다

FULL OUTER JOIN

SELECT *
FROM district_2020
FULL OUTER JOIN district_2035
ON district_2020.id = district_2035.id; -- 두 테이블의 모든 행을 보여줍니다

CROSS JOIN

SELECT *
FROM district_2020
CROSS JOIN district_2035; -- 두 테이블의 모든 행을 보여줍니다

JOIN을 사용한 데이터 탐색

SELECT *
FROM district_2020
JOIN district_2035
ON district_2020.id = district_2035.id
WHERE district_2020.school_2020 <> district_2035.school_2035; -- 두 테이블의 공통된 행만 보여줍니다

JOIN 및 USING

SELECT *
FROM district_2020
JOIN district_2035
USING (id); -- 두 테이블의 공통된 행만 보여줍니다

JOIN 및 NULL

Using NULL to Find Rows with Missing Values / NULL을 사용하여 누락된 값이 있는 행 찾기

SELECT *
FROM district_2020
JOIN district_2035
ON district_2020.id = district_2035.id
WHERE district_2020.id IS NULL; -- 두 테이블의 공통된 행만 보여줍니다

JOIN 및 UNION

SELECT *
FROM district_2020
JOIN district_2035
ON district_2020.id = district_2035.id
WHERE district_2020.id IS NULL
UNION
SELECT *
FROM district_2020
JOIN district_2035
ON district_2020.id = district_2035.id
WHERE district_2035.id IS NULL; -- 두 테이블의 공통된 행만 보여줍니다

JOIN 및 EXCEPT

SELECT *
FROM district_2020
JOIN district_2035
ON district_2020.id = district_2035.id
EXCEPT
SELECT *
FROM district_2020
JOIN district_2035
ON district_2020.id = district_2035.id
WHERE district_2020.school_2020 = district_2035.school_2035; -- 두 테이블의 공통된 행만 보여줍니다

JOIN 및 INTERSECT

SELECT *
FROM district_2020
JOIN district_2035
ON district_2020.id = district_2035.id
INTERSECT
SELECT *
FROM district_2020
JOIN district_2035
ON district_2020.id = district_2035.id
WHERE district_2020.school_2020 = district_2035.school_2035; -- 두 테이블의 공통된 행만 보여줍니다

테이블 관계 이해하기

  • 1:1 (하나의 행이 다른 테이블의 하나의 행과 연결됩니다)
  • 1:N (하나의 행이 다른 테이블의 여러 행과 연결됩니다)
  • N:M (하나의 행이 다른 테이블의 여러 행과 연결되고, 다른 테이블의 행이 하나의 행과 연결됩니다)

1:1

CREATE TABLE teachers (
  id bigserial,
  first_name varchar(25),
  last_name varchar(50),
  school varchar(50),
  hire_date date,
  salary numeric,
  CONSTRAINT teachers_pkey PRIMARY KEY (id)
);

CREATE TABLE teacher_details (
  id bigserial,
  teacher_id bigint,
  address varchar(100),
  phone varchar(20),
  CONSTRAINT teacher_details_pkey PRIMARY KEY (id),
  CONSTRAINT teacher_details_teacher_id_fkey FOREIGN KEY (teacher_id)
      REFERENCES teachers (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

INSERT INTO teachers (first_name, last_name, school, hire_date, salary)
VALUES ('Aaron', 'Snowberger', 'Daejeon University', '2023-09-01', 10000);

INSERT INTO teacher_details (teacher_id, address, phone)
VALUES (1, '123 Main Street', '555-555-5555');

SELECT *
FROM teachers
JOIN teacher_details
ON teachers.id = teacher_details.teacher_id; -- 두 테이블의 공통된 행만 보여줍니다

1:N

CREATE TABLE teachers (
  id bigserial,
  first_name varchar(25),
  last_name varchar(50),
  school varchar(50),
  hire_date date,
  salary numeric,
  CONSTRAINT teachers_pkey PRIMARY KEY (id)
);

CREATE TABLE teacher_details (
  id bigserial,
  teacher_id bigint,
  address varchar(100),
  phone varchar(20),
  CONSTRAINT teacher_details_pkey PRIMARY KEY (id),
  CONSTRAINT teacher_details_teacher_id_fkey FOREIGN KEY (teacher_id)
      REFERENCES teachers (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

INSERT INTO teachers (first_name, last_name, school, hire_date, salary)
VALUES ('Aaron', 'Snowberger', 'Daejeon University', '2023-09-01', 10000);

INSERT INTO teacher_details (teacher_id, address, phone)
VALUES (1, '123 Main Street', '555-555-5555'),
       (1, '456 Main Street', '555-555-5555');

SELECT *
FROM teachers
JOIN teacher_details
ON teachers.id = teacher_details.teacher_id; -- 두 테이블의 공통된 행만 보여줍니다

N:M

CREATE TABLE teachers (
  id bigserial,
  first_name varchar(25),
  last_name varchar(50),
  school varchar(50),
  hire_date date,
  salary numeric,
  CONSTRAINT teachers_pkey PRIMARY KEY (id)
);

CREATE TABLE teacher_details (
  id bigserial,
  teacher_id bigint,
  address varchar(100),
  phone varchar(20),
  CONSTRAINT teacher_details_pkey PRIMARY KEY (id),
  CONSTRAINT teacher_details_teacher_id_fkey FOREIGN KEY (teacher_id)
      REFERENCES teachers (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

CREATE TABLE teacher_subjects (
  id bigserial,
  teacher_id bigint,
  subject varchar(50),
  CONSTRAINT teacher_subjects_pkey PRIMARY KEY (id),
  CONSTRAINT teacher_subjects_teacher_id_fkey FOREIGN KEY (teacher_id)
      REFERENCES teachers (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

INSERT INTO teachers (first_name, last_name, school, hire_date, salary)
VALUES ('Aaron', 'Snowberger', 'Daejeon University', '2023-09-01', 10000);

INSERT INTO teacher_details (teacher_id, address, phone)
VALUES (1, '123 Main Street', '555-555-5555'),
       (1, '456 Main Street', '555-555-5555');

INSERT INTO teacher_subjects (teacher_id, subject)
VALUES (1, 'Math'),
       (1, 'Science');

SELECT *
FROM teachers
JOIN teacher_details
ON teachers.id = teacher_details.teacher_id; -- 두 테이블의 공통된 행만 보여줍니다

Selecting Specific Columns in a Join / 조인에서 특정 열 선택

SELECT teachers.first_name,
       teachers.last_name,
       teacher_details.address,
       teacher_details.phone
FROM teachers
JOIN teacher_details
ON teachers.id = teacher_details.teacher_id; -- 두 테이블의 공통된 행만 보여줍니다

Simplifying JOIN Syntax with Table Aliases / 테이블 별칭을 사용하여 JOIN 구문 단순화

SELECT t.first_name,
       t.last_name,
       td.address,
       td.phone
FROM teachers AS t
JOIN teacher_details AS td
ON t.id = td.teacher_id; -- 두 테이블의 공통된 행만 보여줍니다

Joining Multiple Tables / 여러 테이블 조인

CREATE TABLE district_2020_enrollment (
    id integer,
    enrollment integer
);

CREATE TABLE district_2020_grades (
    id integer,
    grades varchar(10)
);

INSERT INTO district_2020_enrollment
VALUES
    (1, 360),
    (2, 1001),
    (5, 450),
    (6, 927);

INSERT INTO district_2020_grades
VALUES
    (1, 'K-3'),
    (2, '9-12'),
    (5, '6-8'),
    (6, '9-12');

SELECT d20.id,
       d20.school_2020,
       en.enrollment,
       gr.grades
FROM district_2020 AS d20
JOIN district_2020_enrollment AS en
    ON d20.id = en.id
JOIN district_2020_grades AS gr
    ON d20.id = gr.id
ORDER BY d20.id;

Combining Query Results with Set Operators / 집합 연산자를 사용하여 쿼리 결과 결합

SELECT *
FROM district_2020
UNION
SELECT *
FROM district_2035; -- 두 테이블의 공통된 행만 보여줍니다
SELECT *
FROM district_2020
UNION ALL
SELECT *
FROM district_2035; -- 두 테이블의 공통된 행만 보여줍니다
SELECT *
FROM district_2020
INTERSECT
SELECT *
FROM district_2035; -- 두 테이블의 공통된 행만 보여줍니다
SELECT *
FROM district_2020
EXCEPT
SELECT *
FROM district_2035; -- 두 테이블의 공통된 행만 보여줍니다

Performing Math on Joined Table Columns / 조인된 테이블 열에서 수학 수행

 CREATE TABLE us_counties_pop_est_2010 (
    state_fips text,
    county_fips text,
    region smallint,
    state_name text,
    county_name text,
    estimates_base_2010 integer,
    CONSTRAINT counties_2010_key PRIMARY KEY (state_fips, county_fips)
);

COPY us_counties_pop_est_2010
FROM 'C:\YourDirectory\us_counties_pop_est_2010.csv'
WITH (FORMAT CSV, HEADER);

SELECT c2019.county_name,
       c2019.state_name,
       c2019.pop_est_2019 AS pop_2019,
       c2010.estimates_base_2010 AS pop_2010,
       c2019.pop_est_2019 - c2010.estimates_base_2010 AS raw_change,
       round( (c2019.pop_est_2019::numeric - c2010.estimates_base_2010)
           / c2010.estimates_base_2010 * 100, 1 ) AS pct_change
FROM us_counties_pop_est_2019 AS c2019
    JOIN us_counties_pop_est_2010 AS c2010
ON c2019.state_fips = c2010.state_fips
    AND c2019.county_fips = c2010.county_fips
ORDER BY pct_change DESC;

목차로 돌아가기