# Interval Join + 窗口聚合 (订单支付) (FlinkSQL)

## Prompt
我需要你写一段 Flink SQL，用两个 datagen 内置连接器模拟订单流和支付流，先按 order_id 做 Interval Join 匹配订单与支付，再对匹配结果做 10 分钟滚动窗口聚合统计，输出到 console。

**业务背景与目标**：用两张 datagen 内置表分别模拟订单流和支付流。先按 order_id 做 Interval Join（支付时间在订单时间前后 10 分钟内），对匹配上的记录按 10 分钟滚动窗口聚合，统计每个窗口内的订单数和支付总额，输出到 console。

**源表定义**：
- `orders_source`（订单流，datagen 连接器）：
  - order_id INT：订单 ID，随机取值 1~1000000
  - user_id INT：用户 ID，随机取值 1~100000
  - order_time：使用 LOCALTIMESTAMP 生成事件时间，设置 WATERMARK 延迟 60 秒
  - 生成速率：rows-per-second = 10000

- `payments_source`（支付流，datagen 连接器）：
  - order_id INT：订单 ID，随机取值 1~1000000
  - pay_amount DOUBLE：支付金额，随机取值 0~5000
  - pay_time：使用 LOCALTIMESTAMP 生成事件时间，设置 WATERMARK 延迟 60 秒
  - 生成速率：rows-per-second = 10000

**输出表定义**：
- `console_output`（print 连接器）：
  - window_start VARCHAR：滚动窗口起始时间
  - window_end VARCHAR：滚动窗口结束时间
  - order_count BIGINT：窗口内匹配订单数
  - total_pay DOUBLE：窗口内支付总额

**SQL 逻辑**：
- 第一步：orders_source 与 payments_source 做 Interval Join
  - 关联条件：o.order_id = p.order_id
  - 时间窗口：p.pay_time BETWEEN o.order_time - INTERVAL '10' MINUTE AND o.order_time + INTERVAL '10' MINUTE
  - 注意：对 pay_time 做 CAST(pay_time AS TIMESTAMP(3)) 降为普通时间戳
- 第二步：对 Join 结果做 10 分钟 TUMBLE 滚动窗口聚合
  - 使用 TUMBLE 按 o.order_time 作为事件时间
  - 聚合 COUNT(*) AS order_count 和 SUM(p.pay_amount) AS total_pay
  - 使用 TUMBLE_START 和 TUMBLE_END（CAST 为 VARCHAR）

**输出要求**：
- 使用 INSERT INTO console_output 将结果输出
- 输出字段顺序：window_start, window_end, order_count, total_pay

## Reference Solution
-- flinksql_014: Interval Join + 10-min TUMBLE 窗口聚合 (订单支付)
-- 双源 Interval Join → TUMBLE 聚合 → COUNT + SUM

-- 1. 订单流 datagen 源表
CREATE TABLE orders_source (
    order_id INT,
    user_id INT,
    order_time AS LOCALTIMESTAMP,
    WATERMARK FOR order_time AS order_time - INTERVAL '60' SECOND
) WITH (
    'connector' = 'datagen',
    'rows-per-second' = '10000',
    'fields.order_id.kind' = 'random',
    'fields.order_id.min' = '1',
    'fields.order_id.max' = '1000000',
    'fields.user_id.kind' = 'random',
    'fields.user_id.min' = '1',
    'fields.user_id.max' = '100000'
);

-- 2. 支付流 datagen 源表
CREATE TABLE payments_source (
    order_id INT,
    pay_amount DOUBLE,
    pay_time AS LOCALTIMESTAMP,
    WATERMARK FOR pay_time AS pay_time - INTERVAL '60' SECOND
) WITH (
    'connector' = 'datagen',
    'rows-per-second' = '10000',
    'fields.order_id.kind' = 'random',
    'fields.order_id.min' = '1',
    'fields.order_id.max' = '1000000',
    'fields.pay_amount.kind' = 'random',
    'fields.pay_amount.min' = '0',
    'fields.pay_amount.max' = '5000'
);

-- 3. Console 输出表
CREATE TABLE console_output (
    window_start VARCHAR,
    window_end VARCHAR,
    order_count BIGINT,
    total_pay DOUBLE
) WITH (
    'connector' = 'print'
);

-- 4. Interval Join + TUMBLE 窗口聚合
INSERT INTO console_output
SELECT
    CAST(TUMBLE_START(o.order_time, INTERVAL '10' MINUTE) AS VARCHAR) AS window_start,
    CAST(TUMBLE_END(o.order_time, INTERVAL '10' MINUTE) AS VARCHAR) AS window_end,
    COUNT(*) AS order_count,
    SUM(p.pay_amount) AS total_pay
FROM orders_source o
JOIN payments_source p
    ON o.order_id = p.order_id
WHERE
    p.pay_time BETWEEN o.order_time - INTERVAL '10' MINUTE
                   AND o.order_time + INTERVAL '10' MINUTE
GROUP BY
    TUMBLE(o.order_time, INTERVAL '10' MINUTE);