Become a Gold Sponsor

集合操作

SQL 集合操作将多个查询块的结果结合成单个结果。 SQL 标准定义了以下三种集合操作:UNIONINTERSECTEXCEPTUNION ALLINTERSECT ALLEXCEPT ALL

并集(Union)

将两个查询块的所有结果组合成单个结果,省略任何重复项。

获取 customers 和 users 表中的所有名称,不带重复。

PostgreSQL
MySQL
SQLite
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
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
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
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
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
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"