CREATE TABLE IF NOT EXISTS doc_orders_fact (
order_id STRING,
user_id STRING,
product_id STRING,
quantity INT,
amount DECIMAL(10,2),
order_time TIMESTAMP
);
初始加载商品数据
INSERT INTO doc_dim_products VALUES
('P001', '无线蓝牙耳机', '数码配件', 'SoundMax', 299.00, CAST('2026-01-01' AS DATE), NULL, true),
('P002', '机械键盘', '电脑外设', 'KeyPro', 459.00, CAST('2026-01-01' AS DATE), NULL, true),
('P003', '运动跑鞋', '运动户外', 'SpeedRun', 389.00, CAST('2026-01-01' AS DATE), NULL, true),
('P004', '瑜伽垫', '运动户外', 'FlexFit', 128.00, CAST('2026-01-01' AS DATE), NULL, true),
('P005', '保温杯', '家居生活', 'ThermoKeep', 89.00, CAST('2026-01-01' AS DATE), NULL, true);
插入历史订单
INSERT INTO doc_orders_fact VALUES
('O001', 'U101', 'P001', 2, 598.00, CAST('2026-03-10 10:00:00' AS TIMESTAMP)),
('O002', 'U102', 'P002', 1, 459.00, CAST('2026-03-15 14:00:00' AS TIMESTAMP)),
('O003', 'U103', 'P003', 1, 389.00, CAST('2026-04-01 09:00:00' AS TIMESTAMP)),
('O004', 'U104', 'P001', 1, 299.00, CAST('2026-04-20 16:00:00' AS TIMESTAMP));
场景一:商品价格调整 + 品类迁移 + 新商品上架
2026-05-28,运营团队发起三项变更:
P001 无线蓝牙耳机:价格从 299 元调整为 349 元
P003 运动跑鞋:品类从"运动户外"迁移到"健康运动"
P006 智能手环:全新商品上架,定价 199 元
SCD Type 2 的更新分两步执行。
步骤一:关闭旧版本 + 插入全新商品
MERGE INTO
MERGE INTO
一条语句同时处理两件事:对有变化的商品关闭旧版本(
is_current = false
is_current = false
),对全新商品直接插入。
MERGE INTO doc_dim_products AS t
USING (
SELECT 'P001' AS product_id, '无线蓝牙耳机' AS product_name, '数码配件' AS category, 'SoundMax' AS brand, 349.00 AS price, CAST('2026-05-28' AS DATE) AS valid_from
UNION ALL
SELECT 'P003', '运动跑鞋', '健康运动', 'SpeedRun', 389.00, CAST('2026-05-28' AS DATE)
UNION ALL
SELECT 'P006', '智能手环', '数码配件', 'SmartBand', 199.00, CAST('2026-05-28' AS DATE)
) AS s
ON t.product_id = s.product_id AND t.is_current = true
WHEN MATCHED AND (t.price <> s.price OR t.category <> s.category)
THEN UPDATE SET is_current = false, valid_to = CAST('2026-05-28' AS DATE)
WHEN NOT MATCHED
THEN INSERT (product_id, product_name, category, brand, price, valid_from, valid_to, is_current)
VALUES (s.product_id, s.product_name, s.category, s.brand, s.price, s.valid_from, NULL, true);
INSERT INTO doc_dim_products
SELECT
s.product_id,
t.product_name,
s.category,
t.brand,
s.price,
CAST('2026-05-28' AS DATE) AS valid_from,
NULL AS valid_to,
true AS is_current
FROM (
SELECT 'P001' AS product_id, '数码配件' AS category, 349.00 AS price
UNION ALL
SELECT 'P003', '健康运动', 389.00
) AS s
JOIN doc_dim_products AS t
ON t.product_id = s.product_id
AND t.is_current = false
AND t.valid_to = CAST('2026-05-28' AS DATE);
SELECT
o.order_id,
o.order_time,
o.product_id,
p.product_name,
p.category,
p.price AS price_at_order_time,
o.quantity,
o.amount
FROM doc_orders_fact AS o
JOIN doc_dim_products AS p
ON o.product_id = p.product_id
AND o.order_time >= CAST(p.valid_from AS TIMESTAMP)
AND (p.valid_to IS NULL OR o.order_time < CAST(p.valid_to AS TIMESTAMP))
ORDER BY o.order_time;
SELECT product_id, product_name, category, price, valid_from, valid_to, is_current
FROM doc_dim_products
WHERE product_id = 'P001'
ORDER BY valid_from;