集合运算

SQL 集合运算将多个查询块的结果合并为单个结果。
SQL 标准定义了以下四种集合运算:UNIONINTERSECTEXCEPTUNION ALL

Union

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

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

import-pattern
builder-pattern
schema.ts
import { union } from 'drizzle-orm/mssql-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)
);
(select [name] from [sellers])
union
(select [name] from [customers])

Union All

将两个查询块中的所有结果合并为单个结果,并保留重复项。

假设你有两张表,一张表示线上销售,另一张表示店内销售。在这种情况下,你希望将这两张表中的数据合并为一个结果集。由于可能存在重复交易,
你希望保留所有记录,而不是去重。

import-pattern
builder-pattern
schema.ts
import { unionAll } from 'drizzle-orm/mssql-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

仅合并两个查询块结果中共有的那些行,并省略任何重复项。

假设你有两张表,存储学生课程选修信息。
你想找出两个不同院系之间共有的课程,
但你只想要不同的课程名称,并且不关心同一学生对同一课程的多次
选课记录。

在这个场景中,你想找出两个院系之间共有的课程,但不希望
即使同一院系的多个学生选了同一门课,也把这门课统计多次。

import-pattern
builder-pattern
schema.ts
import { intersect } from 'drizzle-orm/mssql-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 [projects_name] from [department_a_projects])
intersect
(select [projects_name] from [department_b_projects])

Except

对于两个查询块 A 和 B,返回 A 中所有不同时存在于 B 中的结果,并省略任何重复项。

假设你有两张表,存储员工项目分配信息。
你想找出某个部门独有、且未与另一个部门共享的项目,并排除重复项。

在这个场景中,你想识别某个部门独有、且
未与另一个部门共享的项目。你不希望把同一个项目
统计多次,即使同一部门的多个员工被分配到了它。

import-pattern
builder-pattern
schema.ts
import { except } from 'drizzle-orm/mssql-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])