집합 연산

집합 연산

SQL 집합 연산은 여러 쿼리 블록의 결과를 단일 결과로 결합합니다. SQL 표준은 다음과 같은 집합 연산을 정의합니다: UNION, INTERSECT, EXCEPT, UNION ALL, INTERSECT ALL, EXCEPT ALL.

Union

두 쿼리 블록의 모든 결과를 단일 결과로 결합하며, 중복을 제거합니다.

customers와 users 테이블에서 중복 없이 모든 이름을 가져옵니다.

PostgreSQL
MySQL
SQLite
SingleStore
MSSQL
CockroachDB
import-pattern
builder-pattern
schema.ts
import { union } from 'drizzle-orm/pg-core'
import { users, customers } from './schema'

const allNamesForUserQuery = db.select({ name: users.name }).from(users);

const result = await union(
	allNamesForUserQuery,
	db.select({ name: customers.name }).from(customers)
).limit(10);
(select "name" from "sellers")
union
(select "name" from "customers")
limit $1

Union All

두 쿼리 블록의 모든 결과를 단일 결과로 결합하며, 중복을 포함합니다.

온라인 판매를 나타내는 테이블과 오프라인 매장 판매를 나타내는 테이블이 있는 시나리오를 고려해봅시다. 이 경우 두 테이블의 데이터를 단일 결과 집합으로 결합하려고 합니다. 중복된 트랜잭션이 있을 수 있으므로 중복을 제거하지 않고 모든 레코드를 유지하려고 합니다.

PostgreSQL
MySQL
SQLite
SingleStore
MSSQL
CockroachDB
import-pattern
builder-pattern
schema.ts
import { unionAll } from 'drizzle-orm/pg-core'
import { onlineSales, inStoreSales } from './schema'

const onlineTransactions = db.select({ transaction: onlineSales.transactionId }).from(onlineSales);
const inStoreTransactions = db.select({ transaction: inStoreSales.transactionId }).from(inStoreSales);

const result = await unionAll(onlineTransactions, inStoreTransactions);
select "transaction_id" from "online_sales"
union all
select "transaction_id" from "in_store_sales"

Intersect

두 쿼리 블록의 결과에 공통으로 있는 행만 결합하며, 중복을 제거합니다.

학생의 강좌 등록 정보를 저장하는 두 테이블이 있다고 가정해봅시다. 두 개의 서로 다른 학과 간에 공통적인 강좌를 찾고자 하며, 고유한 강좌명을 원하고 동일한 학생이 같은 강좌에 여러 번 등록한 것은 세지 않으려고 합니다.

이 시나리오에서는 두 학과 간에 공통적인 강좌를 찾되, 같은 학과의 여러 학생이 같은 강좌에 등록했더라도 같은 강좌를 여러 번 세지 않으려고 합니다.

PostgreSQL
MySQL
SQLite
SingleStore
MSSQL
CockroachDB
import-pattern
builder-pattern
schema.ts
import { intersect } from 'drizzle-orm/pg-core'
import { depA, depB } from './schema'

const departmentACourses = db.select({ courseName: depA.courseName }).from(depA);
const departmentBCourses = db.select({ courseName: depB.courseName }).from(depB);

const result = await intersect(departmentACourses, departmentBCourses);
select "course_name" from "department_a_courses"
intersect
select "course_name" from "department_b_courses"

Intersect All

두 쿼리 블록의 결과에 공통으로 있는 행만 결합하며, 중복을 포함합니다.

고객 주문에 대한 데이터를 포함하는 두 테이블이 있고, 일반 고객과 VIP 고객 모두가 주문한 제품을 식별하려는 시나리오를 고려해봅시다. 이 경우 서로 다른 고객이 여러 번 주문하더라도 각 제품의 수량을 추적하려고 합니다.

이 시나리오에서는 일반 고객과 VIP 고객 모두가 주문한 제품을 찾되, 서로 다른 고객이 같은 제품을 여러 번 주문하더라도 수량 정보를 유지하려고 합니다.

PostgreSQL
MySQL
SQLlite
SingleStore
MSSQL
CockroachDB
import-pattern
builder-pattern
schema.ts
import { intersectAll } from 'drizzle-orm/pg-core'
import { regularCustomerOrders, vipCustomerOrders } from './schema'

const regularOrders = db.select({ 
    productId: regularCustomerOrders.productId,
    quantityOrdered: regularCustomerOrders.quantityOrdered }
).from(regularCustomerOrders);

const vipOrders = db.select({ 
    productId: vipCustomerOrders.productId,
    quantityOrdered: vipCustomerOrders.quantityOrdered }
).from(vipCustomerOrders);

const result = await intersectAll(regularOrders, vipOrders);
select "product_id", "quantity_ordered" from "regular_customer_orders"
intersect all
select "product_id", "quantity_ordered" from "vip_customer_orders"

Except

두 쿼리 블록 A와 B에 대해, B에는 없고 A에만 있는 모든 결과를 반환하며, 중복을 제거합니다.

직원의 프로젝트 할당 정보를 저장하는 두 테이블이 있다고 가정해봅시다. 한 학과에만 고유하고 다른 학과와 공유되지 않는 프로젝트를 찾고자 하며, 중복을 제외하려고 합니다.

이 시나리오에서는 한 학과에만 있고 다른 학과와 공유되지 않는 프로젝트를 식별하려고 합니다. 같은 학과의 여러 직원이 같은 프로젝트에 할당되더라도 같은 프로젝트를 여러 번 세지 않으려고 합니다.

PostgreSQL
MySQL
SQLite
SingleStore
MSSQL
CockroachDB
import-pattern
builder-pattern
schema.ts
import { except } from 'drizzle-orm/pg-core'
import { depA, depB } from './schema'

const departmentACourses = db.select({ courseName: depA.projectsName }).from(depA);
const departmentBCourses = db.select({ courseName: depB.projectsName }).from(depB);

const result = await except(departmentACourses, departmentBCourses);
select "projects_name" from "department_a_projects"
except
select "projects_name" from "department_b_projects"

Except All

두 쿼리 블록 A와 B에 대해, B에는 없고 A에만 있는 모든 결과를 반환하며, 중복을 포함합니다.

고객 주문에 대한 데이터를 포함하는 두 테이블이 있고, VIP 고객이 아닌 일반 고객만 주문한 제품을 식별하려는 시나리오를 고려해봅시다. 이 경우 서로 다른 일반 고객이 여러 번 주문하더라도 각 제품의 수량을 추적하려고 합니다.

이 시나리오에서는 일반 고객만 주문하고 VIP 고객은 주문하지 않은 제품을 찾으려고 합니다. 서로 다른 일반 고객이 같은 제품을 여러 번 주문하더라도 수량 정보를 유지하려고 합니다.

PostgreSQL
MySQL
SQLite
SingleStore
MSSQL
CockroachDB
import-pattern
builder-pattern
schema.ts
import { exceptAll } from 'drizzle-orm/pg-core'
import { regularCustomerOrders, vipCustomerOrders } from './schema'

const regularOrders = db.select({ 
    productId: regularCustomerOrders.productId,
    quantityOrdered: regularCustomerOrders.quantityOrdered }
).from(regularCustomerOrders);

const vipOrders = db.select({ 
    productId: vipCustomerOrders.productId,
    quantityOrdered: vipCustomerOrders.quantityOrdered }
).from(vipCustomerOrders);

const result = await exceptAll(regularOrders, vipOrders);
select "product_id", "quantity_ordered" from "regular_customer_orders"
except all
select "product_id", "quantity_ordered" from "vip_customer_orders"