Data Pipeline(数据管道)
把原始数据变成可信输入
Snowflake layering、dbt models & tests、PySpark transformations;验证 incremental loads(增量加载)、idempotent reruns(幂等重跑)与 bad data handling(坏数据处理)。
- dbt models
- PySpark job
- Data tests
面向 DA 转 DE
用同一个电商项目,把 SQL 分析经验接到 Data Model、可靠的 Data Pipeline、Customer Churn Prediction 和 AWS batch deployment。AI 辅助起草与排错,你亲手运行、核对和修改。
建议两周 · 四次带做 · 每次三小时(含休息)
课程内容预告 · 开班安排待确认


ONE PROJECT · THREE DELIVERABLES
为销售团队准备可信的订单指标,为营销团队准备 Customer Churn Scores。你负责把 Raw Data、Model Inputs、Data Processing 与 Batch Scoring 接成可重复运行的 Data Pipeline。
把原始数据变成可信输入
Snowflake layering、dbt models & tests、PySpark transformations;验证 incremental loads(增量加载)、idempotent reruns(幂等重跑)与 bad data handling(坏数据处理)。
把客户数据变成 predictive model
Customer features(客户特征)、labels(标签)与 historical snapshots(历史快照);交付 training notebook、model artifact、data leakage checks 和 evaluation report。
把 processing 与 scoring 接成 batch jobs
S3/Glue、Snowflake feature tables、SageMaker Batch Transform、Step Functions orchestration 与 CloudWatch logs。
以下为课程项目目标;完整 Snowflake/Spark/ML/AWS 成果仍在准备中。
三条工作流,串起数据准备、模型训练与批量预测。AI 辅助写代码、解释报错和 Code Review,关键结果由你验证。
dbt Models & Tests 负责 Snowflake 转换与 Data Quality;Feature Dataset 同时供 Training 和 Batch Scoring 使用。
从 Feature Dataset 构建历史 Features + Labels,检查 Data Leakage;评估后保存 Model Artifact,供 Batch Transform 加载。
将 Feature Dataset 导出至 S3;Batch Transform 同时读取 Feature Export 与 Model Artifact,输出 Prediction Files。
课程目标架构。 查看已运行的 Python / SQLite 项目 →
RETAILFLOW / LOCAL REFERENCE
RetailFlow 电商订单:第二批新增订单与取消订单到来后,销售额从 A$150 更新到 A$130。 idempotent rerun 不重复计数;缺失商品会阻止错误结果发布。
检查通过
重复明细 O100-L1 只保留一次,三个有效明细对应两个订单。
样例范围:单营业日、固定 AUD;未覆盖同键明细变更、同时间戳的优先级、税费及退款核算。无 scheduling、云端或真实 AI 执行。
源码和输入可以下载,在本地按 README 重现;网页展示已计算结果。
# RetailFlow local reference Synthetic, pre-generated teaching reference. Run `python3 pipeline.py --output result.json` using Python 3 with its standard library. No installation, network, API key, AI call, cloud account or charge is needed. `orders-batch-1.csv` and `lines-batch-1.csv` produce AUD 150 revenue, 2 orders, 4 units and AUD 75 average order value after duplicate line removal. Batch 2 cancels O101 and adds O102, producing AUD 130, 2 orders, 4 units and AUD 65 average order value. Repeating batch 2 leaves the result unchanged. An older O101 paid status cannot override the cancellation. A deliberately injected P999 line must fail validation; it is rolled back and the last valid result is retained. The SQL models and Python runner are the complete implementation of this small SQLite reference. The course's planned Snowflake/dbt models, cloud permissions, scheduler and AI workflow are not implemented here. This is not a production platform or a finished implementation of every course outcome. Scope: a single predefined business date, fixed AUD, current-value product categories, immutable line keys. Changed existing line amounts, equal-timestamp conflicts, full source reconciliation, tax/refund accounting, multiple dates, concurrency and production access controls are outside this reference. Explain these limitations when presenting the project. Ownership: course reference template. A learner must add and verify their own change before describing personal contributions. Do not present the reference as real client work, real learner work, or measured career outcomes.打开文件
"""RetailFlow local reference: stdlib SQLite, synthetic data, no cloud/API calls.
Run: python3 pipeline.py --output result.json
This validates the teaching logic, not the planned Snowflake/dbt implementation.
"""
import argparse
import csv
import json
import sqlite3
from pathlib import Path
ROOT = Path(__file__).resolve().parent
def execute():
db = sqlite3.connect(':memory:')
db.row_factory = sqlite3.Row
db.executescript((ROOT / 'models.sql').read_text())
def load_orders(filename):
for row in csv.DictReader((ROOT / filename).open()):
db.execute('''INSERT INTO orders VALUES (:order_id,:status,:updated_at)
ON CONFLICT(order_id) DO UPDATE SET status=excluded.status,
updated_at=excluded.updated_at WHERE excluded.updated_at > orders.updated_at''', row)
def load_lines(filename):
for row in csv.DictReader((ROOT / filename).open()):
db.execute('''INSERT INTO lines VALUES (:order_id,:line_id,:product_id,:quantity,:unit_price)
ON CONFLICT(order_id,line_id) DO NOTHING''', row)
def validate():
missing = db.execute('''SELECT l.order_id,l.line_id,l.product_id FROM lines l
LEFT JOIN products p USING(product_id) WHERE p.product_id IS NULL''').fetchall()
if missing:
raise ValueError('Missing product reference: ' + json.dumps([dict(r) for r in missing]))
invalid = db.execute('SELECT COUNT(*) FROM lines WHERE quantity<=0 OR unit_price<0').fetchone()[0]
if invalid:
raise ValueError('Invalid quantity or unit price')
def snapshot():
validate()
row = dict(db.execute('SELECT * FROM daily_sales').fetchone())
row['order_count'] = int(row['order_count'])
return row
db.executemany('INSERT INTO products VALUES (?,?)', [('P100','Accessories'),('P101','Stationery'),('P102','Home')])
load_orders('orders-batch-1.csv')
load_lines('lines-batch-1.csv')
first = snapshot()
assert first['revenue'] == 150 and first['order_count'] == 2 and first['units'] == 4
load_orders('orders-batch-2.csv')
load_lines('lines-batch-2.csv')
second = snapshot()
assert second['revenue'] == 130 and second['aov'] == 65
load_orders('orders-batch-2.csv')
load_lines('lines-batch-2.csv')
repeated = snapshot()
assert second == repeated
load_orders('orders-late.csv')
assert snapshot() == second, 'Older paid status must not overwrite latest cancellation'
db.execute('SAVEPOINT invalid_batch')
db.execute("INSERT INTO lines VALUES ('O102','L2','P999',1,99)")
try:
snapshot()
except ValueError as error:
failure = str(error)
else:
raise AssertionError('Missing product should block result publication')
db.execute('ROLLBACK TO invalid_batch')
restored = snapshot()
assert restored == second
return {
'evidence': 'Executed local SQLite reference; synthetic data; no Snowflake/dbt or scheduler validation',
'business_date': '2026-10-01',
'currency': 'AUD',
'stages': [
{'id':'first','label':'第一批:完成去重','status':'passed','result':first,
'explanation':'重复的 O100-L1 只保留一次,三条有效明细对应两个订单。'},
{'id':'second','label':'第二批:更新与取消','status':'passed','result':second,
'explanation':'O101 最新状态变为 cancelled,移出 A$50;O102 新增 A$30。'},
{'id':'repeat','label':'同批重跑','status':'passed','result':repeated,
'explanation':'第二批再次执行,业务结果与上次完全一致;更旧的 paid 状态也不会覆盖取消。'},
{'id':'failure','label':'异常批次:阻止发布','status':'blocked','result':restored,
'explanation':'P999 不存在,检查失败,异常批次回滚;这里显示上一次有效结果,不是本次新结果。','error':failure},
],
'checks': [
{'name':'Duplicate line removed','status':'passed'},
{'name':'Cancellation applied','status':'passed'},
{'name':'Repeated batch unchanged','status':'passed'},
{'name':'Older status ignored','status':'passed'},
{'name':'Missing product blocks publication','status':'passed'},
{'name':'Rollback retains last valid result','status':'passed'},
],
'limitations': ['One business date; fixed AUD; no tax/refund accounting',
'Line changes with the same key are outside this reference implementation',
'Equal update timestamps require a defined tie-breaker in the course implementation',
'No cloud, AI execution, scheduling, or production deployment demonstrated'],
}
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--output', type=Path, default=ROOT / 'result.json')
args = parser.parse_args()
args.output.write_text(json.dumps(execute(), ensure_ascii=False, indent=2) + '\n')
print('Local reference executed: 6 checks passed; wrote', args.output)
打开文件CREATE TABLE products(product_id TEXT PRIMARY KEY, category TEXT NOT NULL);
CREATE TABLE orders(order_id TEXT PRIMARY KEY, status TEXT NOT NULL, updated_at TEXT NOT NULL);
CREATE TABLE lines(
order_id TEXT NOT NULL REFERENCES orders(order_id), line_id TEXT NOT NULL,
product_id TEXT NOT NULL, quantity INTEGER NOT NULL, unit_price REAL NOT NULL,
PRIMARY KEY(order_id,line_id)
);
-- One-date reference. All synthetic orders belong to 2026-10-01 Brisbane time.
-- The course Snowflake/dbt implementation must derive the business date explicitly.
CREATE VIEW valid_lines AS
SELECT l.*, p.category FROM lines l JOIN orders o USING(order_id)
JOIN products p USING(product_id) WHERE o.status IN ('paid','completed');
CREATE VIEW daily_sales AS
SELECT ROUND(COALESCE(SUM(quantity*unit_price),0),2) AS revenue,
COUNT(DISTINCT order_id) AS order_count,
COALESCE(SUM(quantity),0) AS units,
ROUND(SUM(quantity*unit_price)/NULLIF(COUNT(DISTINCT order_id),0),2) AS aov
FROM valid_lines;
打开文件order_id,status,updated_at O100,paid,2026-10-01T00:00:00Z O101,paid,2026-10-01T00:05:00Z打开文件
order_id,line_id,product_id,quantity,unit_price O100,L1,P100,2,40 O100,L1,P100,2,40 O100,L2,P101,1,20 O101,L1,P102,1,50打开文件
order_id,status,updated_at O101,cancelled,2026-10-02T00:00:00Z O102,paid,2026-10-02T00:01:00Z打开文件
{
"evidence": "Executed local SQLite reference; synthetic data; no Snowflake/dbt or scheduler validation",
"business_date": "2026-10-01",
"currency": "AUD",
"stages": [
{
"id": "first",
"label": "第一批:完成去重",
"status": "passed",
"result": {
"revenue": 150.0,
"order_count": 2,
"units": 4,
"aov": 75.0
},
"explanation": "重复的 O100-L1 只保留一次,三条有效明细对应两个订单。"
},
{
"id": "second",
"label": "第二批:更新与取消",
"status": "passed",
"result": {
"revenue": 130.0,
"order_count": 2,
"units": 4,
"aov": 65.0
},
"explanation": "O101 最新状态变为 cancelled,移出 A$50;O102 新增 A$30。"
},
{
"id": "repeat",
"label": "同批重跑",
"status": "passed",
"result": {
"revenue": 130.0,
"order_count": 2,
"units": 4,
"aov": 65.0
},
"explanation": "第二批再次执行,业务结果与上次完全一致;更旧的 paid 状态也不会覆盖取消。"
},
{
"id": "failure",
"label": "异常批次:阻止发布",
"status": "blocked",
"result": {
"revenue": 130.0,
"order_count": 2,
"units": 4,
"aov": 65.0
},
"explanation": "P999 不存在,检查失败,异常批次回滚;这里显示上一次有效结果,不是本次新结果。",
"error": "Missing product reference: [{\"order_id\": \"O102\", \"line_id\": \"L2\", \"product_id\": \"P999\"}]"
}
],
"checks": [
{
"name": "Duplicate line removed",
"status": "passed"
},
{
"name": "Cancellation applied",
"status": "passed"
},
{
"name": "Repeated batch unchanged",
"status": "passed"
},
{
"name": "Older status ignored",
"status": "passed"
},
{
"name": "Missing product blocks publication",
"status": "passed"
},
{
"name": "Rollback retains last valid result",
"status": "passed"
}
],
"limitations": [
"One business date; fixed AUD; no tax/refund accounting",
"Line changes with the same key are outside this reference implementation",
"Equal update timestamps require a defined tie-breaker in the course implementation",
"No cloud, AI execution, scheduling, or production deployment demonstrated"
]
}
打开文件DA/BI 或报表分析工作,掌握 JOIN、GROUP BY,能读简单 Python。命令行和 Git 在课前检查。
围绕一个项目,使用预配置 starter 和参考检查点;AI 辅助起草,课堂用来完成关键操作。
独立修改一个指标、feature 或 data quality rule,保留预期结果、代码差异与验证,讲清楚个人贡献。
CURRICULUM / 4 GUIDED SESSIONS
保留老师的五个模块:Data Roles、Data Warehouse & Data Lake、Machine Learning、Snowflake/Spark、Data Product & AWS。每次三小时含十分钟休息,课前准备和课后练习另计。
建议预留 60–90 分钟检查 SQL、Python、Git 和命令行基础。Snowflake、Spark notebook、historical snapshots、AWS 沙箱和模板需在开班前准备与预演;当前访问方式和额度待确认。
第二课使用课程提供的 historical snapshots 训练模型;第一课新增订单不直接作为已观察到的流失 label。课次顺序用于学习,实际 batch jobs 按依赖执行。
L01 / 180 MIN
为订单、客户与商品确定 data grain,画出 Star Schema 与 Bronze/Silver/Gold data flow,在预配置 Snowflake 环境装载第一批数据。
AI 起草 DDL 和模型说明;你检查 grain、join relationships 和金额口径。
已有 SQL 基础;使用课前准备的 CSV 与 Snowflake 环境。
0–15 分钟
查看课程最终目标:电商 Data Pipeline+Customer Churn Model+AWS Batch Scoring;说明哪些现有样例可看、哪些待制作
15–35 分钟
DA/DE/DS 分工与交接,理解 DA 转 DE 需要承担的数据建设责任
35–60 分钟
OLTP/OLAP、warehouse/lake/lakehouse,介绍 Iceberg/Delta 与 SCD Type 2 的用途和边界
60–90 分钟
AI 辅助设计 Star Schema 与 Bronze/Silver/Gold layers;检查 order grain、dimensions、Primary Key 与金额口径
90–100 分钟
休息
100–145 分钟
在预配置 Snowflake 环境执行 DDL、stage 与 COPY INTO,加载电商 CSV 并检查结果
145–170 分钟
用 reference transformations 形成后续 ML 所需的客户样表,核对 grain、columns 和 prediction time;保存 architecture diagram
170–180 分钟
记录 Data Contract 与输入要求,准备下一课 feature 数据
补完 data model diagram 与 column contract,复现加载,检查客户样表是否满足下一课输入。
原始数据可加载;能解释 fact grain、Data Warehouse 与 Data Lake 的取舍,并说明样表来源。
L02 / 180 MIN
接着同一电商场景,使用带 prediction time 的 historical snapshots 构造 feature 和 label。训练 baseline classifier,解释 evaluation results,再保存供后续 Batch Scoring 使用的模型。
AI 起草 feature 和训练代码;你拒绝 leaky features,并用 evaluation records 说明取舍。
使用课程提供的 historical snapshots;第一课的新订单不能直接当作已观察到的流失 label。
0–15 分钟
回顾客户样表,明确 churn definition、prediction time 与下游营销用途;label window 由课程数据明确给出
15–40 分钟
Supervised/Unsupervised Learning、Generative AI;features、labels、train/validation/test、overfitting 与指标
40–65 分钟
AI 建议候选 feature;逐项审查 prediction time、time-based split、样本 label 及 future-data leakage
65–90 分钟
用课程 historical snapshots 准备 customer features 与 label,检查 train/validation/test 边界
90–100 分钟
休息
100–140 分钟
AI 辅助编写 scikit-learn Logistic Regression 或 Decision Tree notebook;先完成 train/validation/test split,再 fit preprocessing pipeline 并训练模型
140–165 分钟
读取 confusion matrix、precision/recall/AUC,讨论漏判流失与误报的业务成本
165–180 分钟
保存模型、feature 说明、split definitions 与 evaluation records,形成 AWS Batch Scoring 的交付输入
独立审查一个 feature 或调整一个已有 feature,说明 leakage 风险,如实记录验证结果。
能解释 label、prediction time、data splitting 和 evaluation;保留可运行 notebook 与模型,不只展示 accuracy。
L03 / 180 MIN
把一次性 SQL 改成可更新的数据处理流程。完成 Snowflake layering 与 dbt 测试,用 PySpark 实现 transformation logic,核对新批次、rerun 和异常数据。
AI 协助改写 SQL/PySpark 和排错;你用独立样本判断结果是否一致。
使用第一课模型、第二课 feature 定义与预配置 notebook;课后完成个人修改。
0–20 分钟
ETL/ELT、batch/micro-batch/streaming;Snowflake 计算存储分离与 Spark 执行方式
20–65 分钟
AI 辅助写 Snowflake Silver data cleaning,处理 data types、duplicates 和 nulls,再用 MERGE 更新 Gold
65–90 分钟
整理 dbt 模型、依赖、not_null/unique/relationships 测试,核对订单与 customer features 口径
90–100 分钟
休息
100–145 分钟
AI 辅助将 transformation logic 写成 PySpark,读取 Parquet,查看 explain 与 shuffle,写出供下游使用的结果
145–170 分钟
核对两个引擎的 columns 与语义差异,重复批次与迟到更新;故意引入错误并用测试定位
170–180 分钟
提交 SQL/dbt/PySpark 产物,布置个人变化与数据产品交付材料
完成一个指标、feature 或 data quality rule 的独立修改,提交对应验证;按第四课部署清单检查产物。 保留独立小样本核对、idempotent rerun 与一项 bad data 失败记录。
Snowflake 与 PySpark 样例输出有对照;data quality tests、rerun 和 model inputs 能够解释。
L04 / 180 MIN
在预置沙箱中,把 data transformation、customer features 与第二课模型接到同一 batch workflow。运行 scoring job、查看 orchestration 与 logs,模拟一次失败,再完成项目说明和资源清理。
AI 辅助解释配置、logs 和错误;你核对权限、运行状态及实际 scoring output。
依赖前面三课产物、教师预演的沙箱与模板;云额度及访问方式待开班确认。
0–20 分钟
完成Data Product Canvas:营销消费者、决策、owner、Data Contract、freshness、质量、访问和成本上限
20–45 分钟
讲解 S3 → Glue/Spark → Snowflake feature → SageMaker scoring architecture;检查预置权限与资源
45–80 分钟
在已准备沙箱上传数据,执行 Glue transformation,更新 Snowflake Gold 与 feature table 并核对
80–90 分钟
休息
90–125 分钟
在 SageMaker 上传第二课模型、检查 model artifacts 与兼容镜像,执行 batch transform 并写回 scores;路径须教师预演
125–150 分钟
用 Step Functions 模板串接任务,查看 CloudWatch 失败/迟到 Alerting;注入一次 schema 错误并验证
150–170 分钟
展示 Data Pipeline、model evaluation 和 Batch Scoring,讲解个人修改、AI 审查与未覆盖能力
170–180 分钟
检查model endpoints/任务和沙箱清理清单,明确课后审查与后续转型路线
提交完整项目、notebook、model artifacts 与 evaluation records、AWS 运行记录、scoring output、故障记录和个人贡献,等待一次审查与复核。 同步提交架构、Data Contract、README、个人变化和能力缺口;书面审查后修改并申请一次复核。
管道与模型有真实运行证据;scoring inputs/outputs 对应,Alerting 路径可验证;无真实部署证据则标未完成。
第三课实操+课后边界样例
保留新订单、取消订单和迟到更新;同批重复执行不应重复计数,不能只核对一次汇总。
第二批更新与重跑前后对照、确定的 Primary Key 和更新时间规则。
第三课 Data Quality Checks+第四课 Monitoring
保留 duplicate keys、missing references、金额或 schema 异常;说明怎样发现、阻止发布、修复并重跑。
测试失败、定位、修复与最后有效结果记录。
第三课后完成,第四课展示;课后个人审查
学员独立修改一个指标、feature 或 data quality rule,解释需求、改动和验证;不只照抄统一参考解。
个人代码差异、预期结果、验证与讲解。
贯穿四次课
保留任务输入、AI 草稿、接受或拒绝的建议、个人修订和独立核对;逐步从老师示范走向独立修改。
至少一项有原因、有修改、有验证的 AI 建议审查。
课前环境准备+每课提交+最终项目
保留预配置 starter、参考解和追赶检查点;整理 architecture diagram、Data Contract、README、运行方式、业务口径和资源关闭步骤。
项目文件、模型、运行记录与可复现说明;准备状态须如实记录。
课后一次书面审查+一次修改复核
保留模型、代码、质量与个人贡献反馈;按实际证据记录独立完成、指导下完成、概念理解和未涉及,形成下一步路线。
反馈、修改与复核记录;个人能力缺口表,师资与窗口待落实。
延伸内容用于理解技术取舍,不承诺十二小时内完整搭建每个工具。
保留 Apache Iceberg/Delta Lake、Slowly Changing Dimensions(SCD Type 2)、Partitioning、Small Files 与 Processing Cost;SCD Type 2 实现和 Query Optimization 作为延伸材料。
保留 Feature Store、Model Drift、RAG/Vector Search/text-to-SQL 对可信数据的依赖;Snowflake Cortex Classification/Prediction 作为选做对照。
保留 Batch/Micro-batch/Streaming、Snowpipe/Dynamic Tables、Airflow/Dagster、Git/PR/CI 与 Infrastructure as Code(IaC)的用途说明;使用已有模板,不在课内完整搭建每个工具。
保留 Access Control、Data Masking、Row-level Security、PII、Data Freshness 与 Cost Monitoring;Amazon MWAA、SageMaker Real-time Endpoint+API Gateway 作为原参考的选做扩展。
先给业务规则、data grain 与预期,再小步生成 SQL、PySpark 或训练代码。保留 AI 草稿、接受或拒绝的理由、个人修订与独立核对。代码能跑,还要检查数据对不对。
课程设计包含一次个人书面项目审查与一次修改复核。具体师资、服务窗口、回放、答疑和工具额度待正式开班确认。
每项按独立完成、指导下完成、概念理解和未涉及记录,未完成的部分标出待修改。
方案价 899,当前暂按澳元;币种和 GST 口径待确认。建议两周四次带做。具体日期、时区、师资、班额、退款规则及 AI/云费用将随正式开班信息说明。
当前只展示课程内容,不收集报名、不创建订单、不收款。两周是第一段工程实践,不保证就业、转岗或薪资提升。
能读变量、循环、函数和文件操作。完整编程入门不放进四次课,需要提前准备。
会。 feature、label、data leakage checks、baseline classification、evaluation 和模型交付是第二课必做;第三课做可靠输入,第四课接 Batch Scoring。
课程使用预配置环境和模板,练一条批量数据产品路径。real-time endpoint、MWAA 和复杂 Performance Tuning 列为延伸。
暂未开放。当前可先看课程大纲、项目基础样例和源码,正式开班安排确认后再开放报名。