案例背景
某快餐订单表需记录订单状态变化:
-
7月1日 23:58:用户下单并支付(状态=
已支付
) -
7月2日 00:05:门店完成出餐(状态=
已完成
)
关键问题:如何精确查询7月1日当天所有已支付但未完成的订单?
解决方案:拉链表设计
1. 表结构设计
字段 | 示例值 | 说明 |
---|---|---|
order_id | 1001 | 订单ID (主键) |
status | 已支付 →已完成 | 订单状态 |
start_date | 2023-07-01 | 记录生效日期 |
end_date | 2023-07-01 → 9999-12-31 | 记录失效日期(当前有效记录为9999-12-31) |
2. 数据更新流程
Step 1:7月1日初始状态
order_id | status | start_date | end_date |
---|---|---|---|
1001 | 已支付 | 2023-07-01 | 9999-12-31 |
Step 2:7月2日状态变更
-
关闭旧记录:将原有效记录的
end_date
更新为变更前一天(2023-07-01) -
新增记录:插入新状态记录,
start_date=2023-07-02
,end_date=9999-12-31
更新后结果:
order_id | status | start_date | end_date | |
---|---|---|---|---|
1001 | 已支付 | 2023-07-01 | 2023-07-01 | ← 历史记录 |
1001 | 已完成 | 2023-07-02 | 9999-12-31 | ← 当前有效记录 |
3. 关键操作SQL示例
(1) 每日增量更新逻辑
sql:
-- 1. 提取当日变更订单 (从Kafka增量日志获取)
WITH changed_orders AS (
SELECT order_id, new_status
FROM kafka_order_updates
WHERE dt='2023-07-02'
)
-- 2. 关闭旧记录:将变更订单的原有效记录设为过期
INSERT OVERWRITE TABLE dwd_order_zip PARTITION(dt)
SELECT
order_id, status,
start_date,
-- 若该订单当日有变更,则end_date设为昨日
CASE WHEN changed.order_id IS NOT NULL
THEN '2023-07-01'
ELSE end_date END AS end_date,
dt
FROM dwd_order_zip
LEFT JOIN changed_orders changed ON zip.order_id = changed.order_id
WHERE end_date = '9999-12-31'
-- 3. 插入新记录
INSERT INTO TABLE dwd_order_zip PARTITION(dt='2023-07-02')
SELECT
order_id,
new_status AS status,
'2023-07-02' AS start_date, -- 新记录生效日
'9999-12-31' AS end_date -- 标记为当前有效
FROM changed_orders
(2) 查询7月1日未完成订单
sql
SELECT *
FROM dwd_order_zip
WHERE start_date <= '2023-07-01'
AND end_date >= '2023-07-01' -- 关键:锁定7月1日当天有效记录
AND status = '已支付' -- 此时状态尚未变更为"已完成"
4. 拉链表的四大优势
优势 | 案例效果 |
---|---|
历史状态追溯 | 精确查得7月1日有10笔支付未完成的订单 |
存储高效 | 无需每日全量快照(节省70%存储空间) |
业务逻辑完整 | 清晰记录订单从支付→完成的完整生命周期 |
跨天统计准确 | 区分7月1日支付与7月2日完成的业务归属 |