跳到主要内容

6、LLM生成数据仓库数据目录

引言

本文旨在利用ChatGPT自动解读数据库DDL元数据信息以及ETL(Extract, Transform, Load)任务代码,以生产Markdown格式的额实现在图数据库Neo4j中准确生成数据血缘地图。主要目的在于评估ChatGPT在数据仓库领域元数据、ETL任务理解和推理方面的能力。

本文旨在利用ChatGPT自动解读数据库DDL元数据信息以及ETL(Extract, Transform, Load)任务代码,以生产Markdown格式的额数据目录

这一创新将显著提升数据仓库数据治理和数据质量管理的运营和维护效率,实现全面数据来源与去向的追溯,确保数据质量和合规性。血缘地图的自动生成不仅提供深度的数据影响分析,有助于性能优化,同时巩固了元数据管理,提高了问题排查效率。

在企业数字化运营的背景下,数据是生产力的关键,因此数据资产管理的价值在于最大程度地发挥数据的潜力。数据资产管理涉及收集、存储、维护和保护企业的数据资源。数据资产管理有助于确保数据的质量、完整性和可用性,以支持数字化业务流程和决策制定。

数据目录是一个用于记录和描述企业内部数据资源的数据库。它提供了对数据资源的详细信息,包括数据的来源、结构、拥有者、使用权限、数据质量指标以及其他相关信息。数据目录的目的是提高数据的可发现性、可理解性和可共享性,从而支持数据管理、数据治理和数据驱动的决策制定。

数据目录

在企业数字化运营的背景下,数据是生产力的关键,因此数据资产管理的价值在于最大程度地发挥数据的潜力。数据资产管理涉及收集、存储、维护和保护企业的数据资源。数据资产管理有助于确保数据的质量、完整性和可用性,以支持数字化业务流程和决策制定。

数据目录是一个用于记录和描述企业内部数据资源的数据库。它提供了对数据资源的详细信息,包括数据的来源、结构、拥有者、使用权限、数据质量指标以及其他相关信息。数据目录的目的是提高数据的可发现性、可理解性和可共享性,从而支持数据管理、数据治理和数据驱动的决策制定。

大模型数据治理

在数据目录维护和数据治理中,大模型有着大量的应用场景包括:

  1. 数据目录元数据自动生成:通过分析文档、表结构和其他数据源,大模型可以自动提取关键信息,填充目录中的元数据,提高数据的可发现性和理解性。

  2. 自动化数据资产分类和标记:大模型可以帮助自动识别和分类数据资产,根据数据的内容和业务含义,自动为数据添加标签和分类,减轻人工工作负担。

  3. 数据质量评估和监控:大模型可以分析数据的质量指标,自动发现数据质量问题并提供建议修复措施,帮助保持数据的高质量。

  4. 数据开放和共享的支持:大模型可以用于自动生成数据开放目录,为外部用户提供清晰的数据访问说明和文档,促进数据的开放和共享。

大模型的应用可以提高数据目录的自动化程度,大大减少人工工作,提高数据质量和可用性,从而增强企业的数据治理能力。

示例说明

我们在TPC-DS系统的数据模型基础上进行了扩展,构建了涵盖数据明细层、数据服务层和数据应用层的三层模型,并编写了相应的ETL加工任务代码。这一工作旨在更好地验证ChatGPT在实际生产环境中生成数据血缘地图的效果。

数据模型

我们搭建了包括以下三个层次的数据仓库模型:

  1. DWD(Dataware Detail)数据明细层: 指的是接收数据仓库ODS层的原始数据,并进行标准化处理。我们把销售目录事实表门店销售事实表网店销售事实表合并成一张销售事实表
  2. DWS(Dataware Service)数据汇总层: 其主要作用是通过聚合和汇总,将DWD层中的数据按照主题进行汇总,进而提升数据分析性能和效率。我们以客户主题为基础,构建了多个数据聚合模型,其中包括客户每日交易行为客户活跃交易时段活跃的每周周几客户购买最多品牌和品类以及客户累计购买排名等。
  3. ADS(Application Data Store)数据应用层: 其主要存储企业上层应用直接使用的数据,这些应用包括企业决策、报表、分析等。在ADS层我们构建了客户画像表

ETL作业

以下是相关联的ETL任务清单,这些任务专用于执行与上述数据模型相关的数据处理操作。这些ETL任务的代码将与数据库信息一同提交,以供ChatGPT在构建数据血缘地图时使用。

INSERT INTO dwd_sales 
WITH ch_catalog AS (
SELECT MD5(CONCAT(cs_order_number, cs_item_sk)),
cs_order_number,
'catalog',
cs_sold_date_sk,
cs_sold_time_sk,
cs_bill_customer_sk,
cs_item_sk,
cs_quantity,
cs_net_paid_inc_ship_tax
FROM catalog_sales cs
),
ch_store AS (
SELECT MD5(CONCAT(ss_ticket_number, ss_item_sk)),
ss_ticket_number,
'store',
ss_sold_date_sk,
ss_sold_time_sk,
ss_customer_sk,
ss_item_sk,
ss_quantity,
ss_net_paid_inc_tax
FROM store_sales cs
),
ch_web AS (
SELECT MD5(CONCAT(ws_order_number, ws_item_sk)),
ws_order_number,
'web',
ws_sold_date_sk,
ws_sold_time_sk,
ws_bill_customer_sk,
ws_item_sk,
ws_quantity,
ws_net_paid_inc_ship_tax
FROM web_sales cs
)
SELECT * FROM ch_catalog
UNION ALL
SELECT * FROM ch_store
UNION ALL
SELECT * FROM ch_web;



INSERT INTO dws_cust_top_brand
WITH TMP0 AS (
SELECT ds.customer_sk,
i.i_brand ,
COUNT(DISTINCT order_number) AS order_cnt,
ROW_NUMBER() OVER (PARTITION BY customer_sk ORDER BY COUNT(DISTINCT order_number) DESC) AS order_cnt_rank
FROM dwd_sales ds
LEFT JOIN item i ON ds.item_sk = i.i_item_sk
WHERE i.i_brand IS NOT NULL
GROUP BY ds.customer_sk, i.i_brand
)
SELECT customer_sk ,
GROUP_CONCAT(i_brand ORDER BY i_brand SEPARATOR ',') ,
SUM(order_cnt)
FROM TMP0
WHERE order_cnt_rank <= 5
GROUP BY customer_sk;




INSERT INTO dws_cust_top_weekday
WITH TMP0 AS (
SELECT ds.customer_sk,
dd.d_day_name,
COUNT(DISTINCT order_number) AS order_cnt,
ROW_NUMBER() OVER (PARTITION BY customer_sk ORDER BY COUNT(DISTINCT order_number) DESC) AS order_cnt_rank
FROM dwd_sales ds
LEFT JOIN date_dim dd ON ds.sold_date_sk = dd.d_date_sk
WHERE dd.d_day_name IS NOT NULL
GROUP BY ds.customer_sk, dd.d_day_name
)
SELECT customer_sk ,
d_day_name as weekday,
order_cnt
FROM TMP0
WHERE order_cnt_rank = 1 AND d_day_name IS NOT NULL;





INSERT INTO dws_cust_sales_daily
SELECT customer_sk,
dd.d_date,
COUNT(DISTINCT order_number) AS order_count,
SUM(quantity) AS quantity,
SUM(net_paid) AS net_paid,
SUM(CASE WHEN channel = 'catalog' THEN net_paid ELSE 0 END) AS catalog_net_paid ,
SUM(CASE WHEN channel = 'store' THEN net_paid ELSE 0 END) AS store_net_paid ,
SUM(CASE WHEN channel = 'web' THEN net_paid ELSE 0 END) AS web_net_paid,
SUM(CASE WHEN dd.d_weekend = 'Y' THEN net_paid ELSE 0 END) AS weekend_net_paid,
SUM(CASE WHEN dd.d_weekend = 'N' THEN net_paid ELSE 0 END) AS working_day_net_paid,
SUM(CASE WHEN dd.d_holiday = 'Y' THEN net_paid ELSE 0 END) AS holiday_net_paid
FROM dwd_sales ds
LEFT JOIN date_dim dd ON ds.sold_date_sk = dd.d_date_sk
WHERE dd.d_date IS NOT NULL
GROUP BY customer_sk, dd.d_date;



INSERT INTO dws_cust_top_category
WITH TMP0 AS (
SELECT ds.customer_sk,
i.i_category ,
COUNT(DISTINCT order_number) AS order_cnt,
ROW_NUMBER() OVER (PARTITION BY customer_sk ORDER BY COUNT(DISTINCT order_number) DESC) AS order_cnt_rank
FROM dwd_sales ds
LEFT JOIN item i ON ds.item_sk = i.i_item_sk
WHERE i.i_category IS NOT NULL
GROUP BY ds.customer_sk, i.i_category
)
SELECT customer_sk ,
GROUP_CONCAT(i_category ORDER BY i_category SEPARATOR ',') ,
SUM(order_cnt)
FROM TMP0
WHERE order_cnt_rank <= 5
GROUP BY customer_sk;




INSERT INTO dws_cust_top_time_shift
WITH TMP0 AS (
SELECT ds.customer_sk,
td.t_sub_shift,
COUNT(DISTINCT order_number) AS order_cnt,
ROW_NUMBER() OVER (PARTITION BY customer_sk ORDER BY COUNT(DISTINCT order_number) DESC) AS order_cnt_rank
FROM dwd_sales ds
LEFT JOIN time_dim td ON ds.sold_time_sk = td.t_time_sk
GROUP BY ds.customer_sk, td.t_sub_shift
)
SELECT customer_sk,
t_sub_shift AS top_shift,
order_cnt
FROM TMP0
WHERE order_cnt_rank = 1 ;



INSERT INTO dws_cust_sales_rank
WITH TMP0 AS (
SELECT ds.customer_sk,
COUNT(DISTINCT order_number) AS order_cnt,
SUM(net_paid) AS order_amt,
ROW_NUMBER() OVER (ORDER BY COUNT(DISTINCT order_number) DESC) AS order_cnt_rank,
ROW_NUMBER() OVER (ORDER BY SUM(net_paid) DESC) AS order_amt_rank
FROM dwd_sales ds
LEFT JOIN customer c ON ds.customer_sk = c.c_customer_sk
GROUP BY customer_sk
)
SELECT customer_sk,
order_cnt,
order_cnt_rank,
order_cnt_rank * 100/COUNT(1) OVER() AS order_cnt_rank_ratio,
order_amt_rank,
order_amt_rank * 100/COUNT(1) OVER() AS order_amt_rank_ratio
FROM TMP0;



INSERT INTO ads_cust_portrait
WITH TMP0 AS (
SELECT dcsd.customer_sk ,
SUM(order_count) tot_order_cnt,
SUM(net_paid) tot_net_paid,
MIN(biz_date) AS first_order_date,
MAX(biz_date) AS last_order_date,
SUM(store_net_paid) AS store_net_paid ,
SUM(catalog_net_paid) AS catalog_net_paid ,
SUM(web_net_paid) AS web_net_paid,
SUM(weekend_net_paid) AS weekend_net_paid,
SUM(working_day_net_paid) AS working_day_net_paid,
SUM(holiday_net_paid) AS holiday_net_paid
FROM dws_cust_sales_daily dcsd
GROUP BY customer_sk
)
SELECT TMP0.*,
dcsr.order_cnt_rank,
dcsr.order_cnt_rank_ratio,
dcsr.order_amt_rank,
dcsr.order_amt_rank_ratio,
dctw.weekday,
dctw.order_cnt,
dctts.top_shift,
dctts.order_cnt,
dctb.top_brand,
dctc.top_category
FROM TMP0
LEFT JOIN dws_cust_sales_rank dcsr ON TMP0.customer_sk = dcsr.customer_sk
LEFT JOIN dws_cust_top_weekday dctw ON TMP0.customer_sk = dctw.customer_sk
LEFT JOIN dws_cust_top_time_shift dctts ON TMP0.customer_sk = dctts.customer_sk
LEFT JOIN dws_cust_top_brand dctb ON TMP0.customer_sk = dctb.customer_sk
LEFT JOIN dws_cust_top_category dctc ON TMP0.customer_sk = dctc.customer_sk;

代码实现

数据字典生成

本段代码旨在通过解析数据库元数据和ETL作业脚本来构建数据字典,包含三部分内容:

  1. 创建SQLDatabase对象
    此步骤收集数据库的元数据,包含数据定义语言(DDL)和样例数据集,目的是为了使大型语言模型(LLM)深入理解数据库的架构和内容。
  2. 读取ETL作业脚本:
    在这一阶段,系统将遍历etl目录下所有的ETL作业SQL脚本,这些脚本作为LLM的输入信息,用于后续的数据处理和分析。
  3. 数据目录生成提示词
    最后,将上述步骤中收集到的信息综合起来形成提示词,这些提示词旨在为大型语言模型提供必要的背景信息,以便更有效地完成任务。具体内容包括:
    角色设定: 将大模型定位为数据仓库专家,专注于处理与数据仓库相关的任务。
    任务指令:依据收集到的数据库元数据和ETL作业信息,以及指定的表,生成数据字典。考虑到ChatGPT输出的限制,数据字典的生成将逐个表进行,而非一次性完成。
    少样本示例:提供少量的示例,以协助理解如何从提供的输入信息中提炼必要数据,并以Markdown格式的表格进行展示。
    输入信息:明确指出输入信息包括数据库所有表的DDL信息以及ETL作业的详细情况。
# 创建数据库,分别在{user}、{password}、{host}、{database}中填入对应的账户号、密码、主机以及数据库
db = SQLDatabase.from_uri("mysql+pymysql://{user}:{password}@{host}/{database}", sample_rows_in_table_info=0)

#读取ETL作业文件
with open(os.path.join('etl', 'etl_all.sql'), 'r') as file:
etl = file.read()

examples = """
下面是基于INSERT INTO语句抽取源表、源字段、计算方式和加工代码示例:

<输入>INSERT INTO destTable(destCol1,...) SELECT srcCol1, ... FROM srcTable
<输出>
源表:srcTable
源字段:srcCol1
计算方式:直取
加工代码:srcCol1


<输入>
INSERT INTO destTable(destCol1,...)
WITH TMP1 AS (SELECT SUM(srcCol1) AS srcCol11 ... FROM srcTable1 GROUP BY ... )
SELECT srcCol11, ... FROM TMP1 GROUP BY ...
<输出>
源表:srcTable
源字段:srcCol1
计算方式:聚合计算
加工代码:SUM(srcCol1)

<输入>
INSERT INTO destTable(destCol1,...)
WITH TMP1 AS (SELECT srcCol1 ... FROM srcTable1 ),
TMP2 AS (SELECT srcCol2 ... FROM srcTable2 ),
TMP3 AS (SELECT srcCol3 ... FROM srcTable3 ),
SELECT srcCol1, ... FROM TMP1
UNION ALL
SELECT srcCol2, ... FROM TMP2
UNION ALL
SELECT srcCol3, ... FROM TMP3
<输出>
源表:srcTable1,srcTable2,srcTable3
源字段:srcTable1.srcCol2,srcTable1.srcCol2,srcTable3.srcCol3
计算方式:直取
加工代码:srcCol1,srcCol2,srcCol3


<输入>INSERT INTO destTable(destCol1,...) SELECT SUM(srcCol1), ... FROM srcTable GROUP BY ...
<输出>
源表:srcTable
源字段:srcCol1
计算方式:聚合计算
加工代码:SUM(srcCol1)

<输入>INSERT INTO destTable(destCol1,...) SELECT SUM(srcCol1 + srcCol2), ... FROM srcTable1, srcTable2 GROUP BY ...
<输出>
源表:srcTable1, srcTable2
源字段:srcTable1.srcCol1,srcTable1.srcCol2
计算方式:聚合计算
加工代码:SUM(srcTable1.srcCol1 + srcTable1.srcCol2)


<输入>INSERT INTO destTable(destCol1,...) SELECT srcCol1 + srcCol2, ... FROM srcTable1, srcTable2
<输出>
源表:srcTable1, srcTable2
源字段:srcTable1.srcCol1,srcTable1.srcCol2
计算方式:四则运算
加工代码:SUM(srcTable1.srcCol1 + srcTable2.srcCol2)


数据字典的文档的格式如下:

** 这里填写表英文名称(这里填表中文名称)**
业务含义:这里输入表详细的业务含义,概括下表中的字段内容

|字段名称 | 中文名称 | 数据类型 | 源表 | 源字段 | 源字段中文名称 | 计算方式| 加工代码|
|------ | ------ | ------- | --- | ----- | ----- | ----- |----- |
|destCol1| 字段1 | INT | srcTable1 |srcCol1 |源字段1 | 直取 |srcCol1 |
|destCol1| 字段1 | INT | srcTable1,srcTable2,srcTable3|srcCol1,srcCol2,srcCol3|源字段1,源字段2,源字段3|直取|srcCol1,srcCol2,srcCol3|
|destCol2| 字段2 | INT | srcTable1, srcTable2 |srcCol3|源字段3| 聚合计算 | SUM(srcCol3)|
|destCol3| 字段2 | INT | srcTable1, srcTable2 |srcCol3, srcCol4|源字段3, 源字段4| 四则计算 | srcCol3 + srcCol4|
""";

result = llm.invoke(f"""
###指令###
请你以数据仓库专家的角色,为客户输入的表生成数据字典。
请严格按照示例抽取源表、源字段、计算方式以及加工代码。

###示例###
{examples}

###中文翻译示例###
<English> net_paid
<中文> 销售额

<English> top_shift
<中文> 购买最活跃时段

<English> top_brand
<中文> 购买最多品牌

<English> top_category
<中文> 购买最多品类

###输入###
以下是数据库表信息:
{db.table_info}

以下是ETL作业:
{etl}

任务:请为etl_ads_cust_portrait表生成数据字典文档
""");

print(result.content)

提示词示例

在本示例中我们给出了非常复杂的提示词示例,这些示例旨在评估ChatGPT在处理复杂数据字典生成任务中的学习和推理能力。示例包括两部分内容:

  1. 信息抽取示例
    信息抽取示例旨在指导ChatGPT从ETL作业的SQL脚本中提取关键信息的方法。这些信息包括在数据字典加工过程中所涉及的源表、源字段、加工方法,以及具体的加工代码。此任务要求对高级SQL语句的深入理解和分析能力,特别是处理嵌套查询、表连接(JOIN)、以及WITH子句等复杂SQL结构的能力。

    <输入>INSERT INTO destTable(destCol1,...)  SELECT srcCol1, ... FROM srcTable
    <输出>
    源表:srcTable
    源字段:srcCol1
    计算方式:直取
    加工代码:srcCol1


    <输入>
    INSERT INTO destTable(destCol1,...)
    WITH TMP1 AS (SELECT SUM(srcCol1) AS srcCol11 ... FROM srcTable1 GROUP BY ... )
    SELECT srcCol11, ... FROM TMP1 GROUP BY ...
    <输出>
    源表:srcTable
    源字段:srcCol1
    计算方式:聚合计算
    加工代码:SUM(srcCol1)

    ······
  2. 数据字典输出格式示例
    在构建数据字典时,应确保其内容结构丰富以便为工程师和数据科学家提供一份详尽的数据目录。为此,数据字典的涵盖以下三部分信息:

    • 表中(英)文名: 通过对表的命名和其加工任务的分析,提供一个精准的中文翻译。
    • 表业务描述: 深入阐述表的业务背景和逻辑意义,从而使团队成员能够全面把握数据的商业价值和应用场景。
    • 表数据字典: 细致列出每个表中各字段的名称、业务含义及其血缘关系,提供足够的上下文信息,确保团队成员能够有效地解读数据模型。
    数据字典的文档的格式如下:

    ** 这里填写表英文名称(这里填表中文名称)**
    业务含义:这里输入表详细的业务含义,概括下表中的字段内容

    |字段名称 | 中文名称 | 数据类型 | 源表 | 源字段 | 源字段中文名称 | 计算方式| 加工代码|
    |------ | ------ | ------- | --- | ----- | ----- | ----- |----- |
    |destCol1| 字段1 | INT | srcTable1 |srcCol1 |源字段1 | 直取 |srcCol1 |
    |destCol1| 字段1 | INT | srcTable1,srcTable2,srcTable3|srcCol1,srcCol2,srcCol3|源字段1,源字段2,源字段3|直取|srcCol1,srcCol2,srcCol3|
    |destCol2| 字段2 | INT | srcTable1, srcTable2 |srcCol3|源字段3| 聚合计算 | SUM(srcCol3)|
    |destCol3| 字段2 | INT | srcTable1, srcTable2 |srcCol3, srcCol4|源字段3, 源字段4| 四则计算 | srcCol3 + srcCol4|

执行结果

以下呈现了由数据服务层的dws_cust_sales_daily表和数据产品层的ads_cust_protrait表生成的数据目录示例文档。

dws_cust_sales_daily(客户每日销售数据):该表记录了客户每日的销售数据,包括订单数量、销售数量、销售金额等信息,以及不同渠道的销售金额。

字段名称中文名称数据类型源表源字段源字段中文名称计算方式加工代码
customer_sk客户IDBIGINTdwd_salescustomer_sk客户ID直取customer_sk
biz_date业务日期DATEdwd_salessold_date_sk销售日期直取sold_date_sk
order_count订单数量BIGINTdwd_salesorder_number订单数量直取order_number
quantity数量DECIMAL(32, 0)dwd_salesquantity数量直取quantity
net_paid销售金额DECIMAL(29, 2)dwd_salesnet_paid销售金额直取net_paid
catalog_net_paid目录销售金额DECIMAL(29, 2)dwd_salesnet_paid目录销售金额聚合计算SUM(CASE WHEN channel = 'catalog' THEN net_paid ELSE 0 END)
store_net_paid店铺销售金额DECIMAL(29, 2)dwd_salesnet_paid店铺销售金额聚合计算SUM(CASE WHEN channel = 'store' THEN net_paid ELSE 0 END)
web_net_paid网店销售金额DECIMAL(29, 2)dwd_salesnet_paid网店销售金额聚合计算SUM(CASE WHEN channel = 'web' THEN net_paid ELSE 0 END)
weekend_net_paid周末销售金额DECIMAL(29, 2)dwd_salesnet_paid周末销售金额聚合计算SUM(CASE WHEN dd.d_weekend = 'Y' THEN net_paid ELSE 0 END)
working_day_net_paid工作日销售金额DECIMAL(29, 2)dwd_salesnet_paid工作日销售金额聚合计算SUM(CASE WHEN dd.d_weekend = 'N' THEN net_paid ELSE 0 END)
holiday_net_paid节假日销售金额DECIMAL(29, 2)dwd_salesnet_paid节假日销售金额聚合计算SUM(CASE WHEN dd.d_holiday = 'Y' THEN net_paid ELSE 0 END)

etl_ads_cust_portrait(客户画像):该表记录了客户的订单数量、销售额、首次和最后一次订单日期以及不同渠道的销售情况,以及客户的排名和最活跃时段、购买最多品牌和品类。

字段名称中文名称数据类型源表源字段计算方式加工代码
customer_sk客户SKBIGINTdws_cust_sales_daily, dws_cust_top_brand, dws_cust_top_weekday, dws_cust_top_time_shift, dws_cust_top_category, dws_cust_sales_rankcustomer_sk直取customer_sk
tot_order_cnt总订单数DECIMAL(42, 0)dws_cust_sales_dailyorder_count聚合计算SUM(order_count)
tot_net_paid总销售额DECIMAL(51, 2)dws_cust_sales_dailynet_paid聚合计算SUM(net_paid)
first_order_date首次下单日期DATEdws_cust_sales_dailybiz_date聚合计算MIN(biz_date)
last_order_date最后下单日期DATEdws_cust_sales_dailybiz_date聚合计算MAX(biz_date)
store_net_paid门店销售额DECIMAL(51, 2)dws_cust_sales_dailystore_net_paid聚合计算SUM(store_net_paid)
catalog_net_paid目录销售额DECIMAL(51, 2)dws_cust_sales_dailycatalog_net_paid聚合计算SUM(catalog_net_paid)
web_net_paid网络销售额DECIMAL(51, 2)dws_cust_sales_dailyweb_net_paid聚合计算SUM(web_net_paid)
weekend_net_paid周末销售额DECIMAL(51, 2)dws_cust_sales_dailyweekend_net_paid聚合计算SUM(weekend_net_paid)
working_day_net_paid工作日销售额DECIMAL(51, 2)dws_cust_sales_dailyworking_day_net_paid聚合计算SUM(working_day_net_paid)
holiday_net_paid节假日销售额DECIMAL(51, 2)dws_cust_sales_dailyholiday_net_paid聚合计算SUM(holiday_net_paid)
order_cnt_rank订单数量排名BIGINT UNSIGNEDdws_cust_sales_rankorder_cnt_rank直取order_cnt_rank
order_cnt_rank_ratio订单数量排名比例DECIMAL(28, 4)dws_cust_sales_rankorder_cnt_rank_ratio直取order_cnt_rank_ratio
order_amt_rank订单金额排名BIGINT UNSIGNEDdws_cust_sales_rankorder_amt_rank直取order_amt_rank
order_amt_rank_ratio订单金额排名比例DECIMAL(28, 4)dws_cust_sales_rankorder_amt_rank_ratio直取order_amt_rank_ratio
weekday最活跃工作日CHAR(9)dws_cust_top_weekdayweekday直取weekday
order_cnt订单数量BIGINTdws_cust_top_weekdayorder_cnt直取order_cnt
top_shift最活跃时间段CHAR(20)dws_cust_top_time_shifttop_shift直取top_shift
order_cnt订单数量BIGINTdws_cust_top_time_shiftorder_cnt直取order_cnt
top_brand购买最多品牌VARCHAR(256)dws_cust_top_brandtop_brand直取top_brand
order_cnt订单数量BIGINTdws_cust_top_brandorder_cnt直取order_cnt
top_category购买最多品类VARCHAR(256)dws_cust_top_categorytop_category直取top_category