非等值连接
连接条件不限于等号:价格落在区间、两段时间是否重叠,这类场景要用范围或不等条件连接。写法很自然,但非等值条件通常用不上等值索引,而且区间重叠时一行可能命中多条规则,结果行数会被放大。
基本信息
| 条件形式 | ON 支持 >=、<、BETWEEN 等任意布尔表达式 |
|---|---|
| 索引 | 非等值条件难以走等值索引,大表要评估代价 |
| 边界 | 统一左闭右开可避免相邻区间重复命中 |
| 结果行数 | 取决于区间重叠程度 |
| 典型场景 | 价格档位、时间段匹配、范围对照 |
典型使用场景
- 按价格区间匹配优惠规则或费率档位
- 判断两条记录的时间区间是否重叠
- 把明细匹配到所属的统计区间
- 按分数段对照评级
- 核对区间划分里有没有空隙或重叠
示例
示例
-- 区间匹配:统一左闭右开,避免相邻区间重复命中
SELECT p.name, pr.level
FROM products p
JOIN price_rules pr
ON p.price >= pr.min_price
AND p.price < pr.max_price
ORDER BY p.id;
-- 时间区间重叠:两段区间有交集就匹配
SELECT a.id, b.id
FROM appointments a
JOIN appointments b
ON a.id < b.id
AND a.room_id = b.room_id
AND a.starts_at < b.ends_at
AND b.starts_at < a.ends_at;条件形态与代价
| 条件形态 | 能否用索引 | 典型代价 |
|---|---|---|
| 等值 a = b | 可以 | 低 |
| 范围 a BETWEEN b AND c | 通常不能 | 随区间重叠放大行数 |
| 不等 a <> b | 一般不能 | 接近笛卡尔积,慎用 |
| 区间重叠两条件 | 部分可借一侧索引过滤 | 需评估放大倍数 |
区间边界不统一是最常见的错误:相邻区间两端都闭会重复命中,两端都开又会漏掉边界值。统一成「左闭右开」能省掉很多对账麻烦。
先把一侧数据过滤到尽量小再做区间连接:非等值连接的代价主要由候选对数量决定,缩小输入往往比调索引更有效。