必学知识丨什么是笛卡尔积?应用场景有哪些?

虽然笛卡尔积(Cartesian Product) 在大多数日常业务查询中是需要避免的“陷阱”,但在某些特定场景下,它其实是有意且高效的工具。以下是几个适合使用笛卡尔积的典型场景.

应用场景

✅ 场景 1:生成所有可能的组合(组合爆炸)

适用情况:需要枚举两个或多个维度的所有组合。

示例:生成所有“产品 × 颜色”组合用于商品上架

-- 产品表
CREATE TABLE 产品 (
    产品ID INT,
    产品名称 NVARCHAR(50)
);
INSERT INTO 产品 VALUES (1, N'T恤'), (2, N'帽子');

-- 颜色表
CREATE TABLE 颜色 (
    颜色ID INT,
    颜色名称 NVARCHAR(20)
);
INSERT INTO 颜色 VALUES (1, N'红色'), (2, N'蓝色'), (3, N'黑色');

需求:为每种产品生成所有可用颜色的 SKU 草稿。

SELECT 
    p.产品名称,
    c.颜色名称,
    CONCAT(p.产品名称, '-', c.颜色名称) AS SKU名称
FROM 
    产品 p
CROSS JOIN 
    颜色 c;

结果(2 × 3 = 6 行):

产品名称颜色名称SKU名称
T恤红色T恤-红色
T恤蓝色T恤-蓝色
T恤黑色T恤-黑色
帽子红色帽子-红色
帽子蓝色帽子-蓝色
帽子黑色帽子-黑色

✅ 这正是业务需要的“全组合”。


✅ 场景 2:生成日期维度与分类维度的完整报表骨架

适用情况:制作报表时,即使某天某个分类没有数据,也要显示为 0(避免图表断点)。

示例:生成“2025年1月每天 × 所有销售区域”的空骨架

-- 销售区域
CREATE TABLE 区域 (
    区域名称 NVARCHAR(20)
);
INSERT INTO 区域 VALUES (N'华北'), (N'华东'), (N'华南');

-- 生成2025年1月所有日期(SQL Server 用递归CTE)
WITH 日期序列 AS (
    SELECT CAST('2025-01-01' AS DATE) AS 日期
    UNION ALL
    SELECT DATEADD(DAY, 1, 日期)
    FROM 日期序列
    WHERE 日期 < '2025-01-31'
)
SELECT 
    d.日期,
    r.区域名称,
    0 AS 销售额  -- 后续可 LEFT JOIN 实际销售数据填充
FROM 
    日期序列 d
CROSS JOIN 
    区域 r
OPTION (MAXRECURSION 31);

✅ 这样就能确保报表中每一天、每个区域都有记录,即使当天无销售。


✅ 场景 3:测试数据生成

适用情况:开发或测试阶段需要大量模拟数据。

-- 模拟100个用户 × 50个商品 的浏览记录(用于压力测试)
WITH 用户编号 AS (
    SELECT TOP 100 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS 用户ID
    FROM sys.objects a, sys.objects b
),
商品编号 AS (
    SELECT TOP 50 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS 商品ID
    FROM sys.objects
)
SELECT 
    u.用户ID,
    p.商品ID,
    GETDATE() AS 浏览时间
INTO 测试_用户浏览记录
FROM 
    用户编号 u
CROSS JOIN 
    商品编号 p;

✅ 快速生成 100 × 50 = 5000 条测试数据。


✅ 场景 4:配置规则矩阵(如权限、定价策略)

适用情况:为“角色 × 功能”或“客户等级 × 服务类型”预设默认规则。

SELECT 
    角色.角色名称,
    功能.功能名称,
    0 AS 是否允许  -- 默认禁止,后续可 UPDATE 特定组合
FROM 
    (VALUES (N'管理员'), (N'普通用户'), (N'访客')) AS 角色(角色名称)
CROSS JOIN 
    (VALUES (N'删除数据'), (N'导出报表'), (N'修改配置')) AS 功能(功能名称);

✅ 一次性初始化完整的权限矩阵。


⚠️ 使用建议

建议说明
显式使用 CROSS JOIN不要用逗号连接表,避免误操作
控制数据量确保参与笛卡尔积的表行数不会导致结果爆炸(如 1万 × 1万 = 1亿行)
配合后续过滤或聚合通常笛卡尔积只是中间步骤,后续会结合 WHERELEFT JOINGROUP BY 使用

❌ 不适合的场景(常见误区)

  • 查询员工及其所属部门(应使用 INNER JOIN ON 部门ID
  • 统计订单和客户信息(需关联主外键)
  • 任何有明确业务关联关系的表之间

总结

适合使用笛卡尔积的场景关键特征
生成全组合(产品×颜色、课程×时间段)需要“所有可能搭配”
构建报表骨架(日期×分类)保证完整性,防止缺失
生成测试数据快速构造多维模拟数据
初始化配置矩阵(角色×权限)预设默认规则

只要目的明确、数据规模可控,笛卡尔积就是一个强大而合法的 SQL 工具!

1 2

© 版权声明
THE END
喜欢就点赞吧
点赞11 分享