# Dual Window Aggregation (Tumble + Hop) (FlinkSQL)

## Prompt
I need you to write a Flink SQL that uses a datagen built-in table to generate order events, and computes the sales volume and order count per product using both a tumbling window and a sliding window, outputting the results to two separate console tables.

**Business Background and Objective**: Generate order events (`order_id BIGINT`, `product_id INT`, `quantity INT`) using a datagen built-in table. Use `LOCALTIMESTAMP` as the event time and set a 5-second watermark delay.

Compute statistics using two window types:
1. **1-minute tumbling window**: Compute the sales volume `SUM(quantity) AS sales` and order count `COUNT(*) AS order_cnt` per product.
2. **Sliding window** (slides every 30 seconds, covering the past 1 minute): Compute the sales volume `SUM(quantity) AS sales` and order count `COUNT(*) AS order_cnt` per product.

Print the results of both window types to two separate console tables, with each record carrying a window type identifier `window_type`.

**Source Table Definition**:
- `orders_source` (order event stream, datagen connector):
  - `order_id BIGINT`: Order ID, randomly generated in the range 1–1,000,000
  - `product_id INT`: Product ID, randomly generated in the range 1–10,000
  - `quantity INT`: Quantity, randomly generated in the range 1–10
  - `event_time`: Uses `LOCALTIMESTAMP` to generate event time, with a WATERMARK delay of 5 seconds
  - Generation rate: `rows-per-second = 50`

**Output Table Definitions**:
- `console_tumble` (print connector, tumbling window results):
  - `window_type STRING`: Window type identifier, fixed as `'TUMBLE'`
  - `window_start TIMESTAMP(3)`: Window start time
  - `window_end TIMESTAMP(3)`: Window end time
  - `product_id INT`: Product ID
  - `sales INT`: Sales volume of the product within the window
  - `order_cnt BIGINT`: Order count of the product within the window

- `console_hop` (print connector, sliding window results):
  - `window_type STRING`: Window type identifier, fixed as `'HOP'`
  - `window_start TIMESTAMP(3)`: Window start time
  - `window_end TIMESTAMP(3)`: Window end time
  - `product_id INT`: Product ID
  - `sales INT`: Sales volume of the product within the window
  - `order_cnt BIGINT`: Order count of the product within the window

**Aggregation Logic**:
- Tumbling window: `GROUP BY TUMBLE(event_time, INTERVAL '1' MINUTE), product_id`
- Sliding window: `GROUP BY HOP(event_time, INTERVAL '30' SECOND, INTERVAL '1' MINUTE), product_id`
- Aggregation metrics: `SUM(quantity) AS sales`, `COUNT(*) AS order_cnt`
- Both window times and the window type must be explicitly output

**Output Requirements**:
- Use two `INSERT INTO` statements to output to `console_tumble` and `console_hop` respectively.
- Output field order: `window_type`, `window_start`, `window_end`, `product_id`, `sales`, `order_cnt`

## Reference Solution
-- online_004: 双窗口聚合 (Tumble + Hop)
-- 单源生成 @ 50 rows/sec

-- 1. 订单事件 datagen 源表
CREATE TABLE orders_source (
    order_id BIGINT,
    product_id INT,
    quantity INT,
    event_time AS LOCALTIMESTAMP,
    WATERMARK FOR event_time AS event_time - INTERVAL '5' SECOND
) WITH (
    'connector' = 'datagen',
    'rows-per-second' = '50',
    'fields.order_id.kind' = 'random',
    'fields.order_id.min' = '1',
    'fields.order_id.max' = '1000000',
    'fields.product_id.kind' = 'random',
    'fields.product_id.min' = '1',
    'fields.product_id.max' = '10000',
    'fields.quantity.kind' = 'random',
    'fields.quantity.min' = '1',
    'fields.quantity.max' = '10'
);

-- 2. Console 输出表 (Tumble 滚动窗口)
CREATE TABLE console_tumble (
    window_type STRING,
    window_start TIMESTAMP(3),
    window_end TIMESTAMP(3),
    product_id INT,
    sales INT,
    order_cnt BIGINT
) WITH (
    'connector' = 'print'
);

-- 3. Console 输出表 (Hop 滑动窗口)
CREATE TABLE console_hop (
    window_type STRING,
    window_start TIMESTAMP(3),
    window_end TIMESTAMP(3),
    product_id INT,
    sales INT,
    order_cnt BIGINT
) WITH (
    'connector' = 'print'
);

-- 4a. Tumble 1min 滚动窗口：SUM 销量 + COUNT 订单数
INSERT INTO console_tumble
SELECT
    'TUMBLE' AS window_type,
    TUMBLE_START(event_time, INTERVAL '1' MINUTE) AS window_start,
    TUMBLE_END(event_time, INTERVAL '1' MINUTE) AS window_end,
    product_id,
    CAST(SUM(quantity) AS INT) AS sales,
    COUNT(*) AS order_cnt
FROM orders_source
GROUP BY TUMBLE(event_time, INTERVAL '1' MINUTE), product_id;

-- 4b. Hop 滑动窗口 (30s slide, 1min size)：SUM 销量 + COUNT 订单数
INSERT INTO console_hop
SELECT
    'HOP' AS window_type,
    HOP_START(event_time, INTERVAL '30' SECOND, INTERVAL '1' MINUTE) AS window_start,
    HOP_END(event_time, INTERVAL '30' SECOND, INTERVAL '1' MINUTE) AS window_end,
    product_id,
    CAST(SUM(quantity) AS INT) AS sales,
    COUNT(*) AS order_cnt
FROM orders_source
GROUP BY HOP(event_time, INTERVAL '30' SECOND, INTERVAL '1' MINUTE), product_id;