# Order-Payment Interval Join + Windowed Aggregation (FlinkSQL)

## Prompt
I need you to write a Flink SQL that uses two datagen built-in tables to simulate an order stream and a payment stream, performs an Interval Join on `order_id`, and then aggregates the order count and total payment amount over a 10-minute tumbling window, outputting the results to the console.

**Business Background and Objective**: Simulate an order stream and a payment stream using two datagen built-in tables, each generating 100 million records. The `order_id` and `user_id` in the order stream range from 1 to 1,000,000, and the `order_id` in the payment stream also ranges from 1 to 1,000,000. Both tables use `LOCALTIMESTAMP` as the event time and set a 5-second watermark delay.

Perform an Interval Join on the two tables using `order_id`, matching only records where the payment time falls within 10 minutes before or after the order time. Then, aggregate the successfully matched records over a 10-minute tumbling window to compute the order count and total payment amount per window, and finally output the results to the console table.

**Source Table Definitions**:
- `orders_source` (order stream, datagen connector):
  - `order_id INT`: Order ID, randomly generated in the range 1–1,000,000
  - `user_id INT`: User ID, randomly generated in the range 1–1,000,000
  - `event_time`: Uses `LOCALTIMESTAMP` to generate event time, with a WATERMARK delay of 5 seconds
  - Generation rate: `rows-per-second = 1000`

- `payments_source` (payment stream, datagen connector):
  - `order_id INT`: Order ID, randomly generated in the range 1–1,000,000
  - `pay_amount DOUBLE`: Payment amount, randomly generated in the range 1–100,000
  - `event_time`: Uses `LOCALTIMESTAMP` to generate event time, with a WATERMARK delay of 5 seconds
  - Generation rate: `rows-per-second = 1000`

**Output Table Definition**:
- `console_output` (print connector):
  - `window_start VARCHAR`: Window start time
  - `window_end VARCHAR`: Window end time
  - `order_count BIGINT`: Order count within the window
  - `total_pay_amount DOUBLE`: Total payment amount within the window

**Join + Aggregation Logic**:
- Interval Join condition: `orders_source.order_id = payments_source.order_id`
- Time window: `payments_source.event_time BETWEEN orders_source.event_time - INTERVAL '10' MINUTE AND orders_source.event_time + INTERVAL '10' MINUTE`
- Tumbling window: `TUMBLE` 10 minutes
- Aggregation metrics: `COUNT(*) AS order_count`, `SUM(pay_amount) AS total_pay_amount`
- Convert window times to `VARCHAR` for output

**Output Requirements**:
- Use `INSERT INTO console_output` to output the results.
- Output field order: `window_start`, `window_end`, `order_count`, `total_pay_amount`

## Reference Solution
-- online_002: 订单支付 Interval Join + Tumble 窗口聚合
-- 每个源生成 1 亿条数据 @ 1000 rows/sec

-- 1. 订单流 datagen 源表
CREATE TABLE orders_source (
    order_id INT,
    user_id INT,
    event_time AS LOCALTIMESTAMP,
    WATERMARK FOR event_time AS event_time - INTERVAL '5' SECOND
) WITH (
    'connector' = 'datagen',
    'rows-per-second' = '1000',
    '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' = '1000000'
);

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

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

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