Post

🐘 PostgreSQL κΈ°λ³Έ 07 - κ΄€κ³„ν˜• λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ ν…Œμ΄λΈ” 쑰인

🐘 PostgreSQL κΈ°λ³Έ 07 - κ΄€κ³„ν˜• λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ ν…Œμ΄λΈ” 쑰인

πŸ“™ γ€Žμ‹€μš© SQL』을 읽고 μ •λ¦¬ν•œ κΈ€μž…λ‹ˆλ‹€.

Join을 μ‚¬μš©ν•˜μ—¬ ν…Œμ΄λΈ” μ—°κ²°ν•˜κΈ°

  • ANSI SQL ν‘œμ€€μ˜ 일뢀인 JOIN은 ON에 λΆ€μšΈ 값을 μ‚¬μš©ν•˜μ—¬ λ°μ΄ν„°λ² μ΄μŠ€μ˜ ν•œ ν…Œμ΄λΈ”μ„ λ‹€λ₯Έ ν…Œμ΄λΈ”κ³Ό μ—°κ²°ν•œλ‹€.
  • 일반적으둜 λ‹€μŒκ³Ό 같은 ν˜•νƒœλ‘œ μž‘μ„±ν•œλ‹€.
1
2
3
SELECT *
FROM table_a JOIN table_b
ON table_a.key_column = table_b.foreign_key_column;
  • 참고둜 >=, >와 같은 ν‘œν˜„μ‹λ„ λΆ€μšΈ κ²°κ³Ό 값을 λ°˜ν™˜ν•˜λ―€λ‘œ 쑰인 쑰건으둜 μ‚¬μš©ν•  수 μžˆλ‹€.

ν‚€ μ—΄λ‘œ ν…Œμ΄λΈ” μ‘°μΈν•˜κΈ°

ν…Œμ΄λΈ” μƒμ„±ν•˜κΈ°

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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);
dept_iddeptcity
1TaxAtlanta
2ITBoston
  • dept_id 열은 ν…Œμ΄λΈ”μ˜ κΈ°λ³Έ ν‚€λ‹€.
  • μ—¬κΈ°μ„œ κΈ°λ³Έ ν‚€λŠ” ν…Œμ΄λΈ”μ˜ 각 행을 κ³ μœ ν•˜κ²Œ μ‹λ³„ν•˜λŠ” μ—΄ λ˜λŠ” μ—΄ λͺ¨μŒμ΄λ‹€.
  • μœ νš¨ν•œ κΈ°λ³Έ ν‚€ 열은 λ‹€μŒ μ œμ•½ 쑰건이 μ μš©λœλ‹€.
  1. μ—΄ λ˜λŠ” μ—΄ λͺ¨μŒμ€ 각 행에 λŒ€ν•΄ κ³ μœ ν•œ 값을 κ°€μ Έμ•Ό ν•œλ‹€.
  2. μ—΄ λ˜λŠ” μ—΄ λͺ¨μŒμ—λŠ” 결츑값이 μ—†μ–΄μ•Ό ν•œλ‹€.
  • CONSTRAINT ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ departments 및 employees ν…Œμ΄λΈ”μ— λŒ€ν•œ κΈ°λ³Έ ν‚€λ₯Ό μ •μ˜ν•œλ‹€.
emp_idfirst_namelast_namesalarydept_id
1JuliaReyes115,3001
2JanetKing98,0001
3ArthurPappas72,7002
4MichaelTaylor89,5002
  • emp_idλŠ” κΈ°λ³Έ ν‚€, dept_id 열은 departments ν…Œμ΄λΈ”μ˜ κΈ°λ³Έ ν‚€λ₯Ό μ°Έμ‘°ν•˜λŠ” μ™Έλž˜ 킀이닀.
  • μ™Έλž˜ ν‚€ μ œμ•½ 쑰건을 μ‚¬μš©ν•˜λ €λ©΄ μ°Έμ‘°ν•˜λŠ” 열에 ν•΄λ‹Ή 값이 이미 μ‘΄μž¬ν•˜κ³  μžˆμ–΄μ•Ό ν•œλ‹€.
  • 이λ₯Ό 톡해 데이터 무결성을 κ°•ν™”ν•  수 있으며, κΈ°λ³Έ 킀와 달리 μ™Έλž˜ ν‚€ 열은 λΉ„μ–΄ μžˆμ„ 수 있으며, μ€‘λ³΅λœ 값이 ν—ˆμš©λœλ‹€.
  • κ°€λ Ή 두 ν…Œμ΄λΈ” 값을 톡해 Julia의 λΆ€μ„œ IDλŠ” 1이고, ν•΄λ‹Ή λΆ€μ„œλŠ” Atlanta의 Tax λΆ€μ„œμž„μ„ μ•Œ 수 μžˆλ‹€.
deptlocationfirst_namelast_namesalary
TaxAtlantaJuliaReyes115,300
TaxAtlantaJanetKing98,000
ITBostonArthurPappas72,700
ITBostonMichaelTaylor89,500
  • departments ν…Œμ΄λΈ”κ³Ό employees ν…Œμ΄λΈ”λ‘œ λ‚˜λˆ„λ“― κΌ­ 데이터λ₯Ό ꡬ성 μš”μ†Œλ‘œ λ‚˜λˆ μ•Ό ν• κΉŒ?
  • μœ„μ™€ 같이 λͺ¨λ“  데이터λ₯Ό ν•œ ν…Œμ΄λΈ”μ— ν†΅ν•©ν•˜μ—¬ κ΄€λ¦¬ν•œλ‹€λ©΄ λ‹€μŒ λ¬Έμ œκ°€ μžˆλ‹€.
  1. μ—¬λŸ¬ ν•­λͺ©μ˜ 데이터λ₯Ό ν•œ ν…Œμ΄λΈ”μ— 쑰인할 λ•Œ ν•„μ—°μ μœΌλ‘œ 정보λ₯Ό λ°˜λ³΅ν•΄μ•Ό ν•œλ‹€.
    • 수백만 개의 행을 λ‹€λ£¨λŠ” κ²½μš°μ™€ 같이 데이터가 λŠ˜μ–΄λ‚  경우 μ€‘λ³΅λ˜λŠ” λ°μ΄ν„°λ‘œ 인해 λ¦¬μ†ŒμŠ€λ₯Ό 크게 λ‚­λΉ„ν•˜κ²Œ λœλ‹€.
  2. κ΄€λ ¨ μ—†λŠ” 데이터λ₯Ό ν•œ ν…Œμ΄λΈ”μ— λ„£λŠ” 것은 데이터 관리λ₯Ό μ–΄λ ΅κ²Œ λ§Œλ“ λ‹€.
    • λΆ€μ„œμ˜ 이름을 λ³€κ²½ν•œλ‹€λ©΄, ν…Œμ΄λΈ”μ— 각 행에 μ—…λ°μ΄νŠΈκ°€ ν•„μš”ν•˜κ²Œ λœλ‹€.
    • 그런데, 일뢀 ν–‰λ§Œ 잘λͺ» μ—…λ°μ΄νŠΈν•˜κ²Œ λœλ‹€λ©΄ 였λ₯˜κ°€ λ°œμƒν•  수 μžˆλ‹€.
    • ν•˜μ§€λ§Œ ν…Œμ΄λΈ”μ„ λ”°λ‘œ κ΄€λ¦¬ν•œλ‹€λ©΄, λΆ€μ„œ ν…Œμ΄λΈ”μ˜ ν•œ ν–‰λ§Œ 값을 λ°”κΎΈλ©΄ λœλ‹€.
  3. 정보가 μ—¬λŸ¬ ν…Œμ΄λΈ”μ— 걸쳐 μ •κ·œν™”λ˜μ—ˆλ‹€κ³  ν•΄μ„œ μ „μ²΄μ μœΌλ‘œ 정보λ₯Ό μ‚΄νŽ΄λ³΄λŠ” 것이 μ–΄λ ΅μ§€ μ•Šλ‹€.
    • JOIN을 μ‚¬μš©ν•˜λ©΄ λœλ‹€.

JOIN을 μ‚¬μš©ν•˜μ—¬ μ—¬λŸ¬ ν…Œμ΄λΈ” μΏΌλ¦¬ν•˜κΈ°

  • μΏΌλ¦¬μ—μ„œ ν…Œμ΄λΈ”μ„ μ‘°μΈν•˜λ©΄ λ°μ΄ν„°λ² μ΄μŠ€λŠ” μ§€μ •ν•œ 열에 λŒ€ν•΄ ON절의 ν‘œν˜„μ‹μ„ true둜 λ°˜ν™˜ν•˜λŠ” 값이 μžˆλŠ” 두 ν…Œμ΄λΈ”μ˜ 행을 μ—°κ²°ν•œλ‹€.
  • 그러면 두 ν…Œμ΄λΈ”μ˜ 열을 쿼리의 μΌλΆ€λ‘œ μš”μ²­ν•œ 경우, 쿼리 결과에 ν¬ν•¨λ˜κ±°λ‚˜ 쑰인된 ν…Œμ΄λΈ”μ˜ 열을 μ‚¬μš©ν•˜μ—¬ WHERE 절둜 κ²°κ³Όλ₯Ό 필터링할 μˆ˜λ„ μžˆλ‹€.
  • JOIN을 μ‚¬μš©ν•˜λŠ” 예제 μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™λ‹€.
1
2
3
4
SELECT *
FROM employees JOIN departments
ON employees.dept_id = departments.dept_id
ORDER BY employees.dept_id;
emp_idfirst_namelast_namesalarydept_iddept_iddeptcity
1JuliaReyes115,30011TaxAtlanta
2JanetKing98,00011TaxAtlanta
3ArthurPappas72,70022ITBoston
4MichaelTaylor89,50022ITBoston
  • 쿼리 μ‹€ν–‰ κ²°κ³Όμ—λŠ” 두 ν…Œμ΄λΈ”μ˜ λͺ¨λ“  열이 λ‚˜νƒ€λ‚˜κΈ° λ•Œλ¬Έμ—, dept_id 열이 두 번 λ“±μž₯ν•œλ‹€.
  • 이λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄μ„œλŠ” 두 ν…Œμ΄λΈ”μ—μ„œ μ›ν•˜λŠ” μ—΄λ§Œ 검색해야 ν•œλ‹€.

JOIN μœ ν˜• μ΄ν•΄ν•˜κΈ°

  • λ‹€μŒμ€ λ‹€μ–‘ν•œ μ’…λ₯˜μ˜ JOIN에 λŒ€ν•œ μ˜ˆμ‹œμ΄λ‹€.
  1. JOIN
    • INNER JOIN으둜 λŒ€μ²΄ν•  수 μžˆλ‹€.
    • 두 ν…Œμ΄λΈ”μ˜ 쑰인된 μ—΄μ—μ„œ μΌμΉ˜ν•˜λŠ” 값이 μžˆλŠ” 두 ν…Œμ΄λΈ”μ˜ 행을 λ°˜ν™˜ν•œλ‹€.
  2. LEFT JOIN
    • μ™Όμͺ½ ν…Œμ΄λΈ”μ˜ λͺ¨λ“  행을 λ°˜ν™˜ν•œλ‹€.
    • SQL이 였λ₯Έμͺ½ ν…Œμ΄λΈ”μ—μ„œ μΌμΉ˜ν•˜λŠ” 값을 κ°€μ§„ 행을 찾으면 ν•΄λ‹Ή ν–‰μ˜ 값이 ν¬ν•¨λœλ‹€.
    • κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄, 였λ₯Έμͺ½ ν…Œμ΄λΈ”μ˜ 값은 ν‘œμ‹œλ˜μ§€ μ•ŠλŠ”λ‹€. - RIGHT JOIN
    • 였λ₯Έμͺ½ ν…Œμ΄λΈ”μ˜ λͺ¨λ“  행을 λ°˜ν™˜ν•œλ‹€.
    • SQL이 μ™Όμͺ½ ν…Œμ΄λΈ”μ—μ„œ μΌμΉ˜ν•˜λŠ” 값을 κ°€μ§„ 행을 찾으면 ν•΄λ‹Ή ν–‰μ˜ 값이 ν¬ν•¨λœλ‹€.
    • κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄, μ™Όμ™Όμͺ½ ν…Œμ΄λΈ”μ˜ 값은 ν‘œμ‹œλ˜μ§€ μ•ŠλŠ”λ‹€. - FULL OUTER JOIN
    • 두 ν…Œμ΄λΈ”μ—μ„œ λͺ¨λ“  ν–‰μ˜ 값을 λ°˜ν™˜ν•˜κ³ , 값이 μΌμΉ˜ν•˜λŠ” 행은 μ—°κ²°ν•œλ‹€.
    • λ°˜λŒ€ ν…Œμ΄λΈ”μ— μΌμΉ˜ν•˜λŠ” 행이 μ—†λŠ” κ²½μš°μ—λŠ” 쿼리 결과에 λ‹€λ₯Έ ν…Œμ΄λΈ”μ— λŒ€ν•œ 빈 값이 ν¬ν•¨λœλ‹€. - CROSS JOIN
    • 두 ν…Œμ΄λΈ”μ—μ„œ κ°€λŠ₯ν•œ λͺ¨λ“  쑰합을 λ°˜ν™˜ν•œλ‹€.
  • JOIN을 μ‚΄νŽ΄λ³΄κΈ° μœ„ν•œ 두 ν…Œμ΄λΈ”μ„ λ‹€μŒκ³Ό 같이 μƒμ„±ν•˜μž.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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');

JOIN(INNER JOIN)

1
2
3
4
SELECT *
FROM district_2020 JOIN district_2035
ON district_2020.id = district_2035.id
ORDER BY district_2020.id;
  • μœ„ μ½”λ“œμ™€ 같이 JOIN에 μ‚¬μš©ν•œ μ—΄μ—μ„œ μΌμΉ˜ν•˜λŠ” 행을 λ°˜ν™˜ν•˜λ €λ©΄ JOIN λ˜λŠ” INNER JOIN ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€.
  • 두 ν…Œμ΄λΈ”μ— λ™μ‹œμ— μ‘΄μž¬ν•˜λŠ” 학ꡐ IDκ°€ μ„Έ κ°œμ΄λ―€λ‘œ μΏΌλ¦¬λŠ” ν•΄λ‹Ή IDλ₯Ό κ°€μ§„ μ„Έ 개의 ν–‰λ§Œ λ°˜ν™˜ν•œλ‹€.
  • λ˜ν•œ JOIN ν‚€μ›Œλ“œ μ™Όμͺ½μ— 적은 ν…Œμ΄λΈ”μ˜ 열이 κ²°κ³Ό ν…Œμ΄λΈ”μ—μ„œ μ•žμ— ν‘œμ‹œλœλ‹€λŠ” 점을 μœ μ˜ν•΄μ•Ό ν•œλ‹€.
  • JOIN ν‚€μ›Œλ“œλŠ” 일반적으둜 잘 κ΅¬μ‘°ν™”λ˜κ³ , μœ μ§€ 관리가 잘 된 λ°μ΄ν„°μ…‹μ—μ„œ 두 ν…Œμ΄λΈ” λͺ¨λ‘μ— μ‘΄μž¬ν•˜λŠ” ν–‰λ§Œ μ°Ύμ•„μ•Ό ν•˜λŠ” 경우 μ‚¬μš©ν•œλ‹€.

JOINμ—μ„œ USING μ‚¬μš©ν•˜κΈ°

1
2
3
4
SELECT *
FROM district_2020 JOIN district_2035
USING (id)
ORDER BY district_2020.id;
  • JOIN의 ON μ ˆμ— μ‚¬μš©ν•˜λŠ” μ—΄ 이름이 λ™μΌν•œ 경우 USING ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄ 쀑볡 좜λ ₯을 쀄이고, 쿼리λ₯Ό 쀄일 수 μžˆλ‹€.
  • λ‘˜ μ΄μƒμ˜ 열을 κ²°ν•©ν•˜λŠ” 경우 μ‰Όν‘œλ‘œ κ΅¬λΆ„ν•œλ‹€.
  • κ²°κ³ΌλŠ” λ‹€μŒκ³Ό κ°™λ‹€.
idschool_2020school_2035
1Oak Street SchoolOak Street School
2Roosevelt High SchoolRoosevelt High School
6Webutuck High SchoolWebutuck High School

LEFT JOINκ³Ό RIGHT JOIN

  • JOINκ³Ό 달리 각각 ν•œ ν…Œμ΄λΈ”μ˜ λͺ¨λ“  행을 λ°˜ν™˜ν•˜λ©°, λ‹€λ₯Έ ν…Œμ΄λΈ”μ— μΌμΉ˜ν•˜λŠ” 값이 μžˆλŠ” 행이 μ‘΄μž¬ν•œλ‹€λ©΄, 결과에 ν•΄λ‹Ή ν–‰μ˜ 값을 ν¬ν•¨ν•œλ‹€.
1
2
3
4
5
6
7
8
9
10
11
-- LEFT JOIN
SELECT *
FROM district_2020 LEFT JOIN district_2035
ON district_2020.id = district_2035.id
ORDER BY district_2020.id;

-- RIGHT JOIN
SELECT *
FROM district_2020 RIGHT JOIN district_2035
ON district_2020.id = district_2035.id
ORDER BY district_2035.id;
idschool_2020idschool_2035
1Oak Street School1Oak Street School
2Roosevelt High School2Roosevelt High School
5Dover Middle SchoolΒ Β 
6Webutuck High School6Webutuck High School
  • JOIN의 μ™Όμͺ½μ— μžˆλŠ” ν–‰ 4κ°œκ°€ λͺ¨λ‘ ν‘œμ‹œλ˜κ³ , 우츑 ν…Œμ΄λΈ”μ—λŠ” idκ°€ 5인 행이 μ—†μœΌλ―€λ‘œ 값을 λΉ„μ›Œ ν‘œμ‹œν•œλ‹€.
idschool_2020idschool_2035
1Oak Street School1Oak Street School
2Roosevelt High School2Roosevelt High School
Β Β 3Morrison Elementary
Β Β 4Chase Magnet Academy
6Webutuck High School6Webutuck High School
  • RIGHT JOIN도 λ§ˆμ°¬κ°€μ§€λ‹€.
  • JOINκ³Ό λ§ˆμ°¬κ°€μ§€λ‘œ 쑰건을 λ§Œμ‘±ν•˜λ©΄ ON λŒ€μ‹  USING을 μ‚¬μš©ν•  수 μžˆλ‹€.
  • λ‹€μŒκ³Ό 같은 λͺ‡ κ°€μ§€ μƒν™©μ—μ„œ LEFT JOINκ³Ό RIGHT JOIN을 μ‚¬μš©ν•˜κ²Œ λœλ‹€.
  1. 쿼리 결과에 ν•œ ν…Œμ΄λΈ”μ˜ λͺ¨λ“  행이 ν¬ν•¨λ˜κΈ°λ₯Ό μ›ν•˜λŠ” 경우
  2. ν…Œμ΄λΈ” 쀑 ν•˜λ‚˜μ—μ„œ 결츑값을 λͺ¨λ‘ μ°ΎμœΌλ €λŠ” 경우, 예λ₯Ό λ“€μžλ©΄ μ„œλ‘œ λ‹€λ₯Έ 두 기간을 λ‚˜νƒ€λ‚΄λŠ” ν•­λͺ©μ— λŒ€ν•œ 데이터λ₯Ό λΉ„κ΅ν•˜λŠ” 경우
  3. 쑰인된 ν…Œμ΄λΈ”μ˜ 일뢀 행에 μΌμΉ˜ν•˜λŠ” 값이 없을 경우

FULL OUTER JOIN

1
2
3
4
SELECT *
FROM district_2020 FULL OUTER JOIN district_2035
ON district_2020.id = district_2035.id
ORDER BY district_2020.id;
idschool_2020idschool_2035
1Oak Street School1Oak Street School
2Roosevelt High School2Roosevelt High School
5Dover Middle SchoolΒ Β 
6Webutuck High School6Webutuck High School
Β Β 4Chase Magnet Academy
Β Β 3Morrison Elementary
  • 일치 여뢀에 관계 없이 두 ν…Œμ΄λΈ”μ˜ λͺ¨λ“  행을 보기 μœ„ν•΄ μ‚¬μš©ν•œλ‹€.

CROSS JOIN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 일반적인 μ‚¬μš©
SELECT *
FROM district_2020 CROSS JOIN district_2035
ORDER BY district_2020.id, district_2035.id;

-- μ‰Όν‘œ(,) λŒ€μ²΄
SELECT *
FROM district_2020, district_2035
ORDER BY district_2020.id, district_2035.id;

-- JOIN ... ON true λŒ€μ²΄
SELECT *
FROM district_2020 JOIN district_2035 ON true
ORDER BY district_2020.id, district_2035.id;
  • μ™Όμͺ½ ν…Œμ΄λΈ”κ³Ό 였λ₯Έμͺ½ ν…Œμ΄λΈ”μ˜ 각 행을 μ •λ ¬ν•˜μ—¬ κ°€λŠ₯ν•œ λͺ¨λ“  ν–‰ 쑰합을 λ‚˜νƒ€λ‚Έλ‹€.
  • 규λͺ¨κ°€ 큰 ν…Œμ΄λΈ”μ—μ„œλŠ” CROSS JOIN을 ν”Όν•˜λŠ” 것이 μ’‹λ‹€.
  • κ°€λ Ή 각각 25만 개의 행을 κ°€μ§„ 두 ν…Œμ΄λΈ”μ„ CROSS JOINν•œλ‹€λ©΄ 625μ–΅ ν–‰μ˜ κ²°κ³Ό 집합을 μƒμ„±ν•œλ‹€.

NULL을 μ‚¬μš©ν•˜μ—¬ 결츑값이 μžˆλŠ” ν–‰ μ°ΎκΈ°

  • ν…Œμ΄λΈ”μ„ 쑰인할 λ•Œλ§ˆλ‹€ ν•œ ν…Œμ΄λΈ”μ˜ ν‚€ 값이 λ‹€λ₯Έ ν…Œμ΄λΈ”μ— λ‚˜νƒ€λ‚˜λŠ”μ§€, λˆ„λ½λœ 값은 μ—†λŠ”μ§€ 쑰사해야 ν•œλ‹€.
  • μ–΄λ–€ μ΄μœ μ—μ„œλΌλ„ λΆˆμΌμΉ˜λŠ” 생기기 마련이고, μ–΄λ–€ λ°μ΄ν„°λŠ” μ‹œκ°„μ΄ 지남에 따라 λ³€κ²½λ˜μ—ˆμ„ μˆ˜λ„ μžˆλ‹€.
  • 예λ₯Ό λ“€μ–΄ μƒˆμ œν’ˆ ν…Œμ΄λΈ”μ—λŠ” 이전 μ œν’ˆ ν…Œμ΄λΈ”μ—λŠ” μ—†λŠ” μ½”λ“œκ°€ ν¬ν•¨λ˜μ—ˆμ„ 수 μžˆλ‹€.
  • 행이 λ§Žμ§€ μ•Šλ‹€λ©΄ 데이터λ₯Ό ν›‘μ–΄λ³Ό λ•Œ λˆ„λ½λœ 데이터가 μžˆλŠ” 행을 μ‰½κ²Œ 찾을 수 μžˆμ§€λ§Œ, 큰 ν…Œμ΄λΈ”μ„ λ‹€λ£¨λŠ” 경우 μΌμΉ˜ν•˜μ§€ μ•ŠλŠ” λͺ¨λ“  행을 ν‘œμ‹œν•˜λŠ” 필터링 μ „λž΅μ΄ ν•„μš”ν•˜λ‹€.
  • 이λ₯Ό μœ„ν•΄ NULL ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•  것이닀.
1
2
3
4
SELECT *
FROM district_2020 LEFT JOIN district_2035
ON district_2020.id = district_2035.id
WHERE district_2035.id IS NULL;
idschool_2020idschool_2035
5Dover Middle SchoolΒ Β 
  • κ²°κ³ΌλŠ” μ™Όμͺ½ ν…Œμ΄λΈ”μ˜ ν–‰ 쀑 였λ₯Έμͺ½ ν…Œμ΄λΈ”κ³Ό μΌμΉ˜ν•˜μ§€ μ•ŠλŠ” κ°’λ§Œ ν‘œμ‹œν•œλ‹€.
  • 이런 쑰인을 일반적으둜 μ•ˆν‹° 쑰인이라고 λΆ€λ₯Έλ‹€.
  • 였λ₯Έμͺ½ ν…Œμ΄λΈ”μ˜ ν–‰ 쀑 μ™Όμͺ½ ν…Œμ΄λΈ”κ³Ό μΌμΉ˜ν•˜μ§€ μ•ŠλŠ” 값을 ν‘œμ‹œν•˜λ €λ©΄ RIGHT JOIN으둜 λ°”κΎΈκ³ , WHEREμ ˆμ„ district_2020.id IS NULL둜 λ°”κΎΈλ©΄ λœλ‹€.

μ„Έ κ°€μ§€ μœ ν˜•μ˜ ν…Œμ΄λΈ” 관계 μ΄ν•΄ν•˜κΈ°

  • ν…Œμ΄λΈ” κ΄€κ³„μ˜ μ„Έ κ°€μ§€ μœ ν˜•μ€ λ‹€μŒκ³Ό κ°™λ‹€.
  1. μΌλŒ€μΌ 관계
    • 두 ν…Œμ΄λΈ”μ—μ„œ IDκ°€ 같은 행이 ν•˜λ‚˜μ”©λ§Œ μ‘΄μž¬ν•˜λŠ” 경우λ₯Ό λ§ν•œλ‹€.
  2. μΌλŒ€λ‹€ 관계
    • ν•œ ν…Œμ΄λΈ”μ˜ ν‚€ 값이 λ‹€λ₯Έ ν…Œμ΄λΈ”μ˜ μ—¬λŸ¬ μ—΄κ³Ό λ§€μΉ­λ˜λŠ” 경우λ₯Ό λ§ν•œλ‹€.
    • κ°€λ Ή μ œμ‘°μ—…μ²΄ ν…Œμ΄λΈ”κ³Ό μžλ™μ°¨ ν…Œμ΄λΈ”μ„ κ·Έ μ˜ˆμ‹œλ‘œ λ“€ 수 μžˆλ‹€.
  3. λ‹€λŒ€λ‹€ 관계
    • ν•œ ν…Œμ΄λΈ”μ˜ μ—¬λŸ¬ ν•­λͺ©μ΄ λ‹€λ₯Έ ν…Œμ΄λΈ”μ˜ μ—¬λŸ¬ ν•­λͺ©κ³Ό λ§€μΉ­λ˜λŠ” κ²½μš°μ΄λ‹€.

μ‘°μΈμ—μ„œ νŠΉμ • μ—΄ μ„ νƒν•˜κΈ°

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 였λ₯˜ λ°œμƒ
SELECT id
FROM district_2020 LEFT JOIN district_2035
ON district_2020.id = district_2035.id;

-- 별칭 λ―Έμ‚¬μš©
SELECT district_2020.id,
	district_2020.school_2020,
	district_2035.school_2035
FROM district_2020 LEFT JOIN district_2035
ON district_2020.id = district_2035.id
ORDER BY district_2020.id;

-- 별칭 μ‚¬μš©
SELECT d20.id,
	d20.school_2020,
	d35.school_2035
FROM district_2020 AS d20 LEFT JOIN district_2035 AS d35
ON d20.id = d35.id
ORDER BY d20.id;
  • νŠΉμ • 열을 μ„ νƒν•˜λ €λ©΄ SELECT ν‚€μ›Œλ“œ 이후 μ›ν•˜λŠ” μ—΄ 이름을 λ‚˜μ—΄ν•œλ‹€.
  • 첫 번째 μΏΌλ¦¬μ—μ„œ 였λ₯˜κ°€ λ°œμƒν•˜λŠ” μ΄μœ λŠ” idκ°€ μ†ν•˜λŠ” ν…Œμ΄λΈ”μ„ μ§€μ •ν•˜μ§€ μ•Šμ•„ μ–΄λ–€ ν…Œμ΄λΈ”μ˜ idλ₯Ό λ§ν•˜λŠ” 건지 λͺ…ν™•ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€.
  • 였λ₯˜λ₯Ό μˆ˜μ •ν•˜λ €λ©΄ district_2020.id와 같이 ν…Œμ΄λΈ” 이름을 μΆ”κ°€ν•΄μ•Ό ν•œλ‹€.
  • AS ν‚€μ›Œλ“œλ₯Ό 톡해 μ½”λ“œλ₯Ό 단좕할 수 있으며, 별칭을 μ‚¬μš©ν•˜λ”λΌλ„ AS ν‚€μ›Œλ“œλŠ” μƒλž΅ν•΄λ„ λœλ‹€.

μ—¬λŸ¬ ν…Œμ΄λΈ” μ‘°μΈν•˜κΈ°

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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');
  • μ—¬λŸ¬ ν…Œμ΄λΈ”μ„ μ‘°μΈν•˜κΈ° μœ„ν•΄ μš°μ„  예제 ν…Œμ΄λΈ”μ„ μƒμ„±ν•˜μž.
1
2
3
4
5
6
7
8
9
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;
idschool_2020enrollmentgrades
1Oak Street School360K-3
2Roosevelt High School1,0019-12
5Dover Middle School4506-8
6Webutuck High School9279-12
  • ν•„μš”ν•œ 경우 μΆ”κ°€ 쑰인을 μ‚¬μš©ν•˜μ—¬ 쿼리에 더 λ§Žμ€ ν…Œμ΄λΈ”μ„ μ‘°νšŒν•  수 μžˆλ‹€.

μ§‘ν•© μ—°μ‚°μžλ‘œ 쿼리 κ²°κ³Ό κ²°ν•©ν•˜κΈ°

  • μ–΄λ–€ μΈμŠ€ν„΄μŠ€λŠ” 쑰인 결과처럼 λ‹€μ–‘ν•œ ν…Œμ΄λΈ”μ˜ 열이 λ‚˜λž€νžˆ λ°˜ν™˜λ˜μ§€ μ•Šκ³  ν•˜λ‚˜μ˜ 결과둜 좜λ ₯λ˜μ–΄ 데이터λ₯Ό μž¬μ •λ ¬ν•΄μ•Ό ν•œλ‹€.
  • μ΄λ ‡κ²Œ 데이터λ₯Ό μž¬μ‘°μž‘ν•˜λŠ” λ°©λ²•μœΌλ‘œλŠ” ANSI SQL ν‘œμ€€μΈ μ§‘ν•© μ—°μ‚°μž UNION, INTERSECT, EXCEPTκ°€ μžˆλ‹€.
  1. UNION
    • 두 쿼리가 μ£Όμ–΄μ§€λ©΄, 두 번째 쿼리의 행을 첫 번째 쿼리에 μΆ”κ°€ν•˜κ³  쀑볡을 μ œκ±°ν•˜μ—¬ κ²°ν•©λœ 고유 ν–‰ 집합을 μƒμ„±ν•œλ‹€.
    • ꡬ문을 UNION ALL둜 μˆ˜μ •ν•˜λ©΄ 쀑볡을 ν¬ν•¨ν•œ λͺ¨λ“  행이 λ°˜ν™˜λœλ‹€.
  2. INTERSECT
    • 두 쿼리에 λͺ¨λ‘ μ‘΄μž¬ν•˜λŠ” ν–‰λ§Œ λ°˜ν™˜ν•˜κ³ , 쀑볡을 μ œκ±°ν•œλ‹€.
  3. EXCEPT
    • 첫 번째 μΏΌλ¦¬μ—λŠ” μžˆμ§€λ§Œ, 두 번째 μΏΌλ¦¬μ—λŠ” μ—†λŠ” 행을 λ°˜ν™˜ν•œλ‹€.
    • 쀑볡이 μ œκ±°λœλ‹€.

UNIONκ³Ό UNION ALL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-- UNION
SELECT * FROM district_2020

UNION

SELECT * FROM district_2035
ORDER BY id;

-- UNION ALL
SELECT * FROM district_2020

UNION ALL

SELECT * FROM district_2035
ORDER BY id;

-- UNION 쿼리 μ»€μŠ€ν„°λ§ˆμ΄μ§•
SELECT '2020' AS year,
	school_2020 AS school
FROM district_2020

UNION ALL

SELECT '2035' AS year,
	school_2035
FROM district_2035
ORDER BY school, year;
  • 쀑볡을 μ œκ±°ν•˜λ €λ©΄ UNION, 쀑볡을 ν¬ν•¨ν•˜λ €λ©΄ UNION ALL, λ˜ν•œ 쿼리λ₯Ό μ»€μŠ€ν„°λ§ˆμ΄μ§•ν•˜μ—¬ ν•©μΉ˜λŠ” κ³Όμ •μ—μ„œ 열을 μΆ”κ°€ν•  μˆ˜λ„ μžˆλ‹€.

INTERSECT와 EXCEPT

1
2
3
4
5
6
7
8
9
SELECT * FROM district_2020
INTERSECT
SELECT * FROM district_2035
ORDER BY id;

SELECT * FROM district_2020
EXCEPT
SELECT * FROM district_2035
ORDER BY id;
idschool_2020
1Oak Street School
2Roosevelt High School
6Webutuck High School
  • INTERSECT ν‚€μ›Œλ“œλŠ” 두 ν…Œμ΄λΈ”μ— μžˆλŠ” 곡톡 λ°μ΄ν„°λ§Œ 좜λ ₯ν•œλ‹€.
idschool_2020
5Dover Middle School
  • EXCEPT ν‚€μ›Œλ“œλŠ” 첫 번째 쿼리에 μžˆμ§€λ§Œ, 두 번째 μΏΌλ¦¬μ—λŠ” μ—†λŠ” ν–‰λ§Œμ„ λ°˜ν™˜ν•˜κ³ , 쀑볡을 μ œκ±°ν•œλ‹€.
  • μ΄λŸ¬ν•œ ν‚€μ›Œλ“œ 듀은 데이터λ₯Ό 검사할 수 μžˆλŠ” μΆ©λΆ„ν•œ κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€.

쑰인된 ν…Œμ΄λΈ” μ—΄μ—μ„œ μˆ˜ν•™ 계산 μˆ˜ν–‰ν•˜κΈ°

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
  • μˆ˜ν•™ ν•¨μˆ˜λŠ” 쑰인된 ν…Œμ΄λΈ”μ—μ„œλ„ μ‚¬μš©ν•  수 μžˆλ‹€.
county_namestate_namepop_2019pop_2010raw_changepct_change
McKenzie CountyNorth Dakota15,0246,3598,665136.3
Loving CountyTexas1698287106.1
Williams CountyNorth Dakota37,58922,39915,19067.8
Hays CountyTexas230,191157,10373,08846.5
Wasatch CountyUtah34,09123,52510,56644.9
Comal CountyTexas156,209108,52047,68943.9
Trousdale CountyTennessee11,2847,8643,42043.5
  • raw_change 열은 2019λ…„ μΆ”μ •μΉ˜μ—μ„œ 2010λ…„ μΆ”μ •μΉ˜λ₯Ό λΊ€ 값이닀.
  • pct_change 열은 2010λ…„κ³Ό 2019λ…„ μ‚¬μ΄μ˜ λ³€ν™”μœ¨μ„ κ³„μ‚°ν•œ 값이닀.
  • 두 ν…Œμ΄λΈ”μ—μ„œ μ£Ό μ½”λ“œμ™€ μΉ΄μš΄ν‹° μ½”λ“œμ˜ 쑰합이 κ³ μœ ν•œ μΉ΄μš΄ν‹°λ₯Ό λ‚˜νƒ€λ‚΄κΈ° λ•Œλ¬Έμ—, AND 논리 μ—°μ‚°μžλ₯Ό 톡해 두 쑰건을 κ²°ν•©ν•œλ‹€.
This post is licensed under CC BY 4.0 by the author.