# 01 · 表结构解析实现

> 目标：解析现有账单表（事实表）+ 维度表的 DDL，识别出**度量字段、维度外键、口径字段**，作为本体建模的输入。

## 1. 输入：现有表结构（示例）

数仓已产出的账单表 + 维度表：

```sql
-- 账单表（事实表）
CREATE TABLE dwd_bill (
    bill_id     BIGINT       COMMENT '账单ID',
    bill_amount DECIMAL(18,2) COMMENT '账单金额',   -- 度量字段
    bill_count  BIGINT       COMMENT '账单数',      -- 度量字段（恒1，SUM聚合）
    region_id   BIGINT       COMMENT '地区外键',    -- 维度外键
    date_id     BIGINT       COMMENT '日期外键',    -- 维度外键
    dt          STRING       COMMENT '日期(yyyy-mm-dd)',
    status      STRING       COMMENT '状态:paid/unpaid',  -- 口径字段
    refunded    BOOLEAN      COMMENT '是否退款'           -- 口径字段
) COMMENT '账单事实表';

-- 维度表：地区
CREATE TABLE dim_region (
    region_id    BIGINT COMMENT '地区ID',
    region_name  STRING COMMENT '地区名(上海)',
    region_group STRING COMMENT '大区(华东区)'
) COMMENT '地区维度表';

-- 维度表：日期
CREATE TABLE dim_date (
    date_id BIGINT COMMENT '日期ID',
    dt      STRING COMMENT '日期',
    month   STRING COMMENT '月',
    year    STRING COMMENT '年'
) COMMENT '日期维度表';
```

## 2. 解析目标：三类字段识别

| 字段类型 | 识别规则 | 示例 |
|---------|---------|------|
| **度量字段** | 数值型、可聚合（DECIMAL/INT，非主键非外键） | bill_amount、bill_count |
| **维度外键** | `*_id` 结尾、关联维度表 | region_id、date_id |
| **口径字段** | 枚举/布尔，参与指标过滤 | status、refunded |

## 3. 解析实现（Java）

```java
public class TableSchemaParser {
    /** 解析表 DDL，识别三类字段 */
    public ParsedTable parse(String tableName) {
        List<ColumnMeta> columns = getColumns(tableName); // DESC 或 information_schema
        ParsedTable t = new ParsedTable(tableName);
        for (ColumnMeta c : columns) {
            if (isMeasure(c))     t.measures.add(c);      // 数值型 + 非主外键
            else if (isDimFK(c))  t.dimFks.add(c);        // *_id 结尾
            else if (isCaliber(c)) t.calibers.add(c);     // 枚举/布尔
        }
        return t;
    }

    private boolean isMeasure(ColumnMeta c) {
        return (c.type.startsWith("DECIMAL") || c.type.startsWith("INT")
                || c.type.startsWith("BIGINT") || c.type.startsWith("DOUBLE"))
               && !c.name.endsWith("_id") && !c.isPk;
    }
    private boolean isDimFK(ColumnMeta c) {
        return c.name.endsWith("_id");
    }
    private boolean isCaliber(ColumnMeta c) {
        return "BOOLEAN".equals(c.type) || c.comment.contains("状态") || c.comment.contains("是否");
    }
}
```

## 4. 解析结果（结构化输出）

```
账单表 dwd_bill 解析结果：
  度量字段：bill_amount（账单金额）、bill_count（账单数）
  维度外键：region_id → dim_region、date_id → dim_date
  口径字段：status（状态）、refunded（是否退款）
  日期字段：dt

维度表 dim_region 解析结果：
  维度字段：region_name（地区名）、region_group（大区）
```

这个解析结果直接喂给 02 本体建模，用于生成指标本体。

## 5. 关键注意

- **度量 vs 口径要区分**：bill_amount 是度量（可聚合），status/refunded 是口径（过滤条件），不能混淆
- **维度外键要关联维度表**：region_id → dim_region，这是维度层级推理的基础
- **解析规则可配置**：字段类型、命名约定因业务而异，识别规则做成可配置的，不要写死
- **解析是半自动**：DDL 能自动解析大部分，但"哪个字段是度量、哪个是口径"最终要人工确认（口径是业务语义，机器只能辅助）
