# Session Window User Behavior Aggregation (FlinkSQL)

## Prompt
I need you to write a Flink SQL that uses a datagen built-in table to simulate a user behavior stream, performs session window aggregation to compute behavioral metrics per user within each session, and outputs the results to the console.

**Business Background and Objective**: Simulate a user behavior data stream using a datagen built-in table that generates 50 records per second, containing four fields: `userId` (user ID, string of length 6), `action` (action type, string of length 8), `action_time` (action occurrence time, timestamp), and `ftime` (event time, timestamp). Based on this datagen table, using `ftime` as the event time (with a 5-second watermark delay), perform a 30-minute session window (`SESSION`) aggregation grouped by `userId`. Compute the following metrics for each user within each session window: session start time, session end time, total action count, number of distinct action types, and the last action time (the maximum value of `action_time`). Output the results to a built-in console table.

**Source Table Definition**:
- `user_source` (user behavior stream, datagen connector):
  - `userId VARCHAR`: User ID, randomly generated, 6 characters in length
  - `action VARCHAR`: Action type, randomly generated, 8 characters in length
  - `action_time TIMESTAMP(3)`: Action occurrence time
  - `ftime`: Uses `LOCALTIMESTAMP` to generate event time, with a WATERMARK delay of 5 seconds
  - Generation rate: `rows-per-second = 50`

**Output Table Definition**:
- `console_output` (print connector):
  - `user_id VARCHAR`: User ID
  - `session_start TIMESTAMP`: Session start time
  - `session_end TIMESTAMP`: Session end time
  - `action_count BIGINT`: Total action count
  - `unique_actions BIGINT`: Number of distinct action types
  - `last_action_time TIMESTAMP`: Last action time

**Query Logic**:
- Window: `SESSION(ftime, INTERVAL '30' MINUTE)` session window
- Grouping: Group by `userId` and the session window
- Aggregation: `COUNT(*)` for total action count, `COUNT(DISTINCT action)` for distinct action type count, `MAX(action_time)` for last action time
- Window functions: Use `SESSION_START` / `SESSION_END` to obtain the window start and end times

**Output Requirements**:
- Use `INSERT INTO console_output` to output the results.
- Output field order: `user_id`, `session_start`, `session_end`, `action_count`, `unique_actions`, `last_action_time`

## Reference Solution
-- flinksql_008: 会话窗口用户行为聚合
-- datagen 生成用户行为流 @ 50 rows/sec, SESSION 30min 窗口聚合

-- 1. 用户行为流 datagen 源表
CREATE TABLE user_source (
    userId VARCHAR,
    action VARCHAR,
    action_time TIMESTAMP(3),
    ftime AS LOCALTIMESTAMP,
    WATERMARK FOR ftime AS ftime - INTERVAL '5' SECOND
) WITH (
    'connector' = 'datagen',
    'rows-per-second' = '50',
    'fields.userId.length' = '6',
    'fields.action.length' = '8'
);

-- 2. Console 输出表
CREATE TABLE console_output (
    user_id VARCHAR,
    session_start TIMESTAMP,
    session_end TIMESTAMP,
    action_count BIGINT,
    unique_actions BIGINT,
    last_action_time TIMESTAMP
) WITH (
    'connector' = 'print'
);

-- 3. SESSION 30min 窗口聚合: 统计每个用户每段会话的行为指标
INSERT INTO console_output
SELECT
    userId AS user_id,
    SESSION_START(ftime, INTERVAL '30' MINUTE) AS session_start,
    SESSION_END(ftime, INTERVAL '30' MINUTE) AS session_end,
    COUNT(*) AS action_count,
    COUNT(DISTINCT action) AS unique_actions,
    MAX(action_time) AS last_action_time
FROM user_source
GROUP BY SESSION(ftime, INTERVAL '30' MINUTE), userId;