【FDE系列】阶段2:Day 32:多表查询 — JOIN 与聚合

📚前言

📒FDE系列内容总纲:

【大纲】FDE 前沿部署工程师学习系列教程-CSDN博客

🚄前置课程列表:

见文档结尾附录。


🚀阶段2·Day 32:多表查询 --- JOIN 与聚合

FDE 学习系列教程 · 第二阶段 · 第 3 周 · Day 2 预计时长:3 小时 | 难度:★★★☆☆ | 前置知识:Day 31 单表增删改查
📌 一句话目标:搞懂为什么要拆表、什么是主键外键,熟练用 INNER JOIN / LEFT JOIN 关联多张业务表,用 GROUP BY + 聚合函数做分组统计。


🧑‍🤝‍🧑 开场:为什么不能把数据全塞一张表?

回忆昨天的 devices 表,里面有个 owner 字段存着"李工"这种文字。图省事是吧?但客户的真实系统绝不会这么设计

为什么?来,看个翻车现场。假设你把设备和负责人信息全塞一张表:

复制代码
❌ 全塞一张表(反范式设计):

devices 表:
| id | 设备名    | 负责人 | 手机号      | 车间   |
|----|----------|--------|------------|--------|
| 1  | 注塑机A1  | 李工   | 138xxx     | 一车间 |
| 2  | 注塑机A2  | 李工   | 138xxx     | 一车间 |   ← 李工信息重复 3 遍
| 3  | 注塑机A3  | 李工   | 138xxx     | 一车间 |

发现问题了吗?同一个李工,名字、手机号、车间被抄了 3 份(他管 30 台设备就抄 30 份)。这会引发三大灾难:

  1. 改不动:李工换手机号了,你得改 30 条记录,漏改 1 条数据就对不上

  2. 存得乱:同一手机号可能存成 "138 xxx"、"138-xxx"、"138xxx" 三种格式

  3. 占空间:大量重复信息,纯浪费

正确做法是拆表------各存各的,用编号关联:

复制代码
✅ 拆成两张表(范式化设计):

engineers(工程师表):          devices(设备表):
| id | 名字 | 手机号  | 车间   |  | id | 设备名   | engineer_id |
|----|------|--------|--------|  |----|---------|-------------|
| 1  | 李工 | 138xxx | 一车间 |  | 1  | 注塑机A1 | 1           |
| 2  | 王工 | 139xxx | 二车间 |  | 2  | 注塑机A2 | 1           |
                                  | 3  | 注塑机A3 | 2           |

改手机号?只改 engineers 表 id=1 这一处,30 台设备自动跟着"变"。
查数据?设备表只有编号 1,名字要去工程师表找------这就需要 JOIN。

📌 一句话:拆表是为了"一处修改,处处生效";JOIN 是为了查询时把拆开的数据再拼回来。


📖 一、主键、外键:表和表之间的"桥"

这里要拐个弯了,稍微费点脑子,但摸透了后面处处通透。

复制代码
┌────────────────────────────────────────────────────────────┐
│  主键(Primary Key)                                        │
│    · 一张表里唯一标识每一行的列(通常叫 id)                 │
│    · 不能重复、不能为空                                      │
│    · 相当于一个人的身份证号                                  │
│                                                            │
│  外键(Foreign Key)                                        │
│    · 一张表里"指向另一张表主键"的列                          │
│    · devices.engineer_id 就是外键,指向 engineers.id        │
│    · 它是表与表之间的"桥"                                   │
└────────────────────────────────────────────────────────────┘

  engineers 表                          devices 表
  ┌────┬──────┐                        ┌────┬──────────┬─────────────┐
  │ id │ name │  ◄──── 主键            │ id │ name     │ engineer_id │  ──┐
  ├────┼──────┤                        ├────┼──────────┼─────────────┤   │
  │  1 │ 李工 │                        │  1 │ 注塑机A1  │      1  ●───┼───┘
  │  2 │ 王工 │                        │  2 │ 注塑机A2  │      1  ●───┼──┐
  └────┴──────┘                        │  3 │ 注塑机A3  │      2  ●───┼──┤
        ▲                              └────┴──────────┴─────────────┘  │
        └────────────────────────── 外键指向主键 ───────────────────────┘

表关系的三种形态(FDE 看客户的 ER 图时会遇到):

关系 说法 例子
一对多(1:N) 一个工程师管多台设备 工程师 1 ──< 设备 N
一对一(1:1) 一个员工对应一份档案 用户 1 ── 1 身份证
多对多(M:N) 一个学生选多门课,一门课多个学生 需要中间表拆成两个 1:N

💡 现实中 90% 的关联是"一对多" ,今天的三张表就是这种。多对多不用慌,它本质是"两张一对多 + 一张中间表",比如工单和标签之间加一张 ticket_tags 关联表。


🖥️ 二、实操:建三张关联表并插数据

今天我们搭一个迷你"工厂管理系统":工程师表、设备表、工单表。这三张表是 FDE 最常见的数据形态。

新建 04_multi_table.py

复制代码
"""
建三张关联表:engineers / devices_new / tickets
文件:04_multi_table.py
"""
import sqlite3

conn = sqlite3.connect("fde_workshop.db")
cur = conn.cursor()

# ① 工程师表
cur.execute("""
    CREATE TABLE IF NOT EXISTS engineers (
        id         INTEGER PRIMARY KEY AUTOINCREMENT,
        name       TEXT NOT NULL,
        phone      TEXT,
        department TEXT,
        title      TEXT DEFAULT '工程师'
    )
""")

# ② 设备表(用 engineer_id 外键关联工程师)
cur.execute("DROP TABLE IF EXISTS devices_new")   # 重建,避免昨天结构干扰
cur.execute("""
    CREATE TABLE devices_new (
        id          INTEGER PRIMARY KEY AUTOINCREMENT,
        name        TEXT NOT NULL,
        type        TEXT NOT NULL,
        temperature REAL DEFAULT 0,
        vibration   REAL DEFAULT 0,
        is_running  INTEGER DEFAULT 1,
        engineer_id INTEGER,
        created_at  TEXT DEFAULT (datetime('now','localtime')),
        FOREIGN KEY (engineer_id) REFERENCES engineers(id)
    )
""")

# ③ 工单表(一张工单关联一台设备 + 一个上报人)
cur.execute("""
    CREATE TABLE IF NOT EXISTS tickets (
        id          INTEGER PRIMARY KEY AUTOINCREMENT,
        device_id   INTEGER NOT NULL,
        title       TEXT NOT NULL,
        priority    TEXT DEFAULT '中',
        status      TEXT DEFAULT '待处理',
        reporter_id INTEGER,
        created_at  TEXT DEFAULT (datetime('now','localtime')),
        FOREIGN KEY (device_id)   REFERENCES devices_new(id),
        FOREIGN KEY (reporter_id) REFERENCES engineers(id)
    )
""")

# 插 4 个工程师
cur.executemany(
    "INSERT INTO engineers (name, phone, department, title) VALUES (?,?,?,?)",
    [("李工","13800001111","一车间","高级工程师"),
     ("王工","13800002222","二车间","工程师"),
     ("赵工","13800003333","一车间","工程师"),
     ("陈工","13800004444","二车间","实习生")]
)

# 插 5 台设备(最后一列是 engineer_id)
cur.executemany("""
    INSERT INTO devices_new (name,type,temperature,vibration,is_running,engineer_id)
    VALUES (?,?,?,?,?,?)
""", [
    ("注塑机A1","注塑",65, 8,1,1),
    ("注塑机A2","注塑",82,12,1,2),
    ("注塑机A3","注塑",91,16,1,3),
    ("冲压机B1","冲压",75, 9,0,1),
    ("冲压机B2","冲压",88, 6,1,4),
])

# 插 5 张工单(设备id, 标题, 优先级, 状态, 上报人id)
cur.executemany("""
    INSERT INTO tickets (device_id,title,priority,status,reporter_id)
    VALUES (?,?,?,?,?)
""", [
    (1,"温度偏高","高","处理中",3),
    (3,"温度严重超标","高","处理中",3),
    (2,"振动异常","中","待处理",2),
    (5,"例行保养","低","已解决",1),
    (3,"振动超标","中","待处理",2),
])

conn.commit()
for t in ["engineers","devices_new","tickets"]:
    cur.execute(f"SELECT COUNT(*) FROM {t}")
    print(f"  {t:12s}:{cur.fetchone()[0]} 条")
conn.close()
print("✅ 三张表建好,数据已插入")

运行:

复制代码
python 04_multi_table.py

  engineers   :4 条
  devices_new :5 条
  tickets     :5 条
✅ 三张表建好,数据已插入

三张表的关系图(务必看懂这个)

复制代码
  engineers(工程师)
  ┌────┬──────┬────────┐
  │ id │ name │ 车间    │
  │ 1  │ 李工 │ 一车间  │
  │ 2  │ 王工 │ 二车间  │
  │ 3  │ 赵工 │ 一车间  │
  │ 4  │ 陈工 │ 二车间  │
  └─▲──┴──────┴────────┘
    │                          ┌─────────────────────┐
    │ reporter_id(上报人)     │ tickets(工单)      │
    └──────────────────────────│ id                  │
                               │ device_id ──┐        │
                               │ title       │        │
                               │ priority    │        │
                               │ status      │        │
                               └─────────────┼────────┘
                                             │
  engineers(工程师)                         │ device_id
  ┌────┬──────┐                              │
  │ id │ name │◄──── engineer_id ───────────┤
  └────┴──────┘                              ▼
              ┌──────────────────────────────────────┐
              │ devices_new(设备)                   │
              │ id │ name     │ type │ temperature   │
              │ 1  │ 注塑机A1  │ 注塑 │ 65            │
              │ 3  │ 注塑机A3  │ 注塑 │ 91            │
              └──────────────────────────────────────┘

  读法:
  · 一台设备属于一个工程师(devices.engineer_id → engineers.id)
  · 一张工单挂在一台设备上(tickets.device_id → devices.id)
  · 一张工单有一个上报人(tickets.reporter_id → engineers.id)

🖥️ 三、INNER JOIN:两边都匹配上的才保留

需求:查每台设备的名称和它的负责人姓名 。设备表只有 engineer_id(编号 1、2、3),名字得去工程师表捞------JOIN 登场。

在 DBeaver 的 SQL 编辑器里写(推荐),或新建 05_join.py

复制代码
SELECT
    d.name        AS 设备名,
    d.temperature AS 温度,
    e.name        AS 负责人,
    e.department  AS 车间
FROM devices_new d
INNER JOIN engineers e
        ON d.engineer_id = e.id;

结果

复制代码
设备名     | 温度 | 负责人 | 车间
注塑机A1   | 65.0 | 李工   | 一车间
注塑机A2   | 82.0 | 王工   | 二车间
注塑机A3   | 91.0 | 赵工   | 一车间
冲压机B1   | 75.0 | 李工   | 一车间
冲压机B2   | 88.0 | 陈工   | 二车间

把 JOIN 语法拆开揉碎

复制代码
SELECT d.name, e.name        -- 要哪些列(用 别名.列名 区分)
FROM   devices_new d         -- 主表,起别名 d(AS 可省略)
INNER JOIN engineers e       -- 要拼接的表,起别名 e
        ON d.engineer_id = e.id;   -- 拼接条件:编号对得上
        └────────────────────┘
              这座"桥"在哪

逐块理解:

部分 作用
FROM devices_new d 以设备表为主,顺手起个短名 d
INNER JOIN engineers e 把工程师表 e 拼进来
ON d.engineer_id = e.id 拼接规则:设备表的外键 = 工程师表的主键
AS 设备名 给结果列起中文名(仅显示用)

💡 为什么要起别名? 两张表都有 idname 列,不写表名数据库分不清你要哪个。d.name 表示"设备表的 name",e.name 表示"工程师表的 name",一目了然。

INNER JOIN 图示(交集)

复制代码
   devices(设备)                 engineers(工程师)
  ┌─────────────────┐            ┌─────────────────┐
  │ A1 → engineer 1 │────────────│ id 1  李工       │
  │ A2 → engineer 2 │────────────│ id 2  王工       │
  │ A3 → engineer 3 │────────────│ id 3  赵工       │
  │ B9 → engineer 9 │     ✗      │ id 4  陈工       │  ◄── B9 指向的 9 不存在
  └─────────────────┘            └─────────────────┘
                          │
                          ▼  INNER JOIN 结果
                 只有"桥两边都接上"的行才保留
                 B9 因为找不到 id=9,直接消失

INNER JOIN = 取交集:两边能对上号的行才出现,对不上的统统丢掉。


🖥️ 四、LEFT JOIN:左边全保留,右边没有的补 NULL

换个需求:找出"一张工单都没有"的设备

用 INNER JOIN 能做到吗?做不到------INNER JOIN 会把"没有工单的设备"丢掉,而那恰恰是你要找的。这时候用 LEFT JOIN

复制代码
SELECT
    d.name  AS 设备名,
    t.title AS 工单标题
FROM devices_new d
LEFT JOIN tickets t
       ON t.device_id = d.id;

先看这个查询的完整结果(左表设备全部保留):

复制代码
设备名     | 工单标题
注塑机A1   | 温度偏高
注塑机A2   | 振动异常
注塑机A3   | 温度严重超标
注塑机A3   | 振动超标        ← A3 有 2 张工单,所以出现 2 行
冲压机B1   | NULL            ← B1 没有工单,右表补 NULL
冲压机B2   | 例行保养

再加一个 WHERE,把右表为 NULL 的捞出来,就是答案:

复制代码
SELECT d.name AS 没有工单的设备
FROM devices_new d
LEFT JOIN tickets t ON t.device_id = d.id
WHERE t.id IS NULL;     -- 右表拼不上(为 NULL)的

没有工单的设备
冲压机B1

INNER vs LEFT 一图看懂

复制代码
  INNER JOIN(内连接)             LEFT JOIN(左连接)

  左表        右表                 左表        右表
  ┌───┐      ┌───┐                ┌───┐      ┌───┐
  │ A │ ●────● a │               │ A │ ●────● a │
  │ B │ ●────● b │               │ B │ ●────● b │
  │ C │ ✗    └───┘               │ C │ ●    NULL │  ← C 保留,右边补空
  └───┘                          └───┘
  结果:A、B(2行)                结果:A、B、C(3行)
  对不上的两边都不保留             左表全保留,右边对不上填 NULL

📌 经典套路记牢LEFT JOIN 右表 ... WHERE 右表.主键 IS NULL 专门用来回答"找出没有 XXX 的 YYY":

  • 没有工单的设备

  • 没有下过单的客户

  • 没有员工的部门

  • 从没被借阅过的图书

💡 还有个 RIGHT JOIN(右连接,右边全保留),实际极少用------把表位置一换,LEFT JOIN 就能实现,所以业界基本只写 LEFT JOIN。


🖥️ 五、三表 JOIN:一条 SQL 串起工单、设备、人

真实报表常要"工单标题 + 设备名 + 上报人姓名",信息分散在三张表。别怕,这个概念听着唬人,拆开看就那么回事------三表 JOIN 就是做两次两表 JOIN

复制代码
SELECT
    t.id       AS 工单号,
    t.title    AS 标题,
    t.priority AS 优先级,
    t.status   AS 状态,
    d.name     AS 设备名,
    e.name     AS 上报人
FROM tickets t
INNER JOIN devices_new d ON t.device_id   = d.id    -- 第1次拼:工单→设备
INNER JOIN engineers   e ON t.reporter_id = e.id    -- 第2次拼:工单→工程师
ORDER BY t.priority DESC, t.created_at DESC;

结果

复制代码
工单号 | 标题          | 优先级 | 状态   | 设备名   | 上报人
1    | 温度偏高       | 高    | 处理中 | 注塑机A1 | 赵工
2    | 温度严重超标   | 高    | 处理中 | 注塑机A3 | 赵工
3    | 振动异常       | 中    | 待处理 | 注塑机A2 | 王工
5    | 振动超标       | 中    | 待处理 | 注塑机A3 | 王工
4    | 例行保养       | 低    | 已解决 | 冲压机B2 | 李工

执行逻辑:数据库先拿工单表,按 device_id 拼上设备名,再按 reporter_id 拼上上报人姓名。每次 JOIN 都是在"加列"。

⚠️ 多表 JOIN 避坑 :SELECT 里的列名最好都带上表别名(t.id 而不是 id),因为三张表里可能有同名列(比如都有 id、created_at),不写清楚数据库会报"ambiguous column(列名有歧义)"。


🖥️ 六、聚合函数 + GROUP BY:分组统计

JOIN 解决"拼列",GROUP BY 解决"合并行做统计"。

需求:按车间统计设备数量和平均温度。一个车间有好几台设备,我们想每个车间只出一行统计数字:

复制代码
SELECT
    e.department                          AS 车间,
    COUNT(*)                              AS 设备数,
    ROUND(AVG(d.temperature), 1)          AS 平均温度,
    MAX(d.temperature)                    AS 最高温度,
    MIN(d.temperature)                    AS 最低温度
FROM devices_new d
INNER JOIN engineers e ON d.engineer_id = e.id
GROUP BY e.department;

结果

复制代码
车间   | 设备数 | 平均温度 | 最高温度 | 最低温度
一车间 | 3     | 77.0    | 91.0    | 65.0
二车间 | 2     | 85.0    | 88.0    | 82.0

聚合函数全家福

函数 作用 例子
COUNT(*) 统计行数(包括 NULL 这个车间有几台设备
COUNT(列名) 统计该列非 NULL 的行数 有几个人填了手机号
SUM(列) 求和 所有设备振动值总和
AVG(列) 平均值 平均温度
MAX(列) / MIN(列) 最大 / 最小值 最高温 / 最低温

💡 ROUND(值, 1) 是保留 1 位小数,纯粹让结果好看。COUNT(*)COUNT(列) 的区别是个高频面试点:前者数所有行,后者只数该列不是 NULL 的行。

GROUP BY 的"行→组"变化

复制代码
分组前(每台设备一行):          GROUP BY department 后(每车间一行):

设备      车间   温度              车间    COUNT  AVG
注塑机A1  一车间 65                一车间   3     77.0
冲压机B1  一车间 75       ───►     二车间   2     85.0
注塑机A3  一车间 91
注塑机A2  二车间 82
冲压机B2  二车间 88
   5 行被"压扁"成 2 行,每行为一组的统计值

⚠️ GROUP BY 黄金规则 :SELECT 后面,除了聚合函数包起来的列,其他列必须出现在 GROUP BY 里SELECT department, name, COUNT(*) ... GROUP BY department 是错的------一个车间有 3 个设备名,数据库不知道该显示哪个。

HAVING:分组之后再筛选

需求:找出工单数量 ≥ 2 的设备

注意:过滤条件是"分组后的统计结果",这时候 WHERE 不够用了(WHERE 在分组之前 执行),得用 HAVING

复制代码
SELECT
    d.name        AS 设备名,
    COUNT(t.id)   AS 工单数
FROM devices_new d
LEFT JOIN tickets t ON t.device_id = d.id
GROUP BY d.id, d.name
HAVING COUNT(t.id) >= 2;       -- 分组后,只留工单数≥2的组

设备名   | 工单数
注塑机A3 | 2

WHERE vs HAVING(最容易混的点)

复制代码
  ┌────────────────────────────────────────────────────────┐
  │  WHERE  → 分组"之前"过滤行(针对原始的每一行)          │
  │  HAVING → 分组"之后"过滤组(针对聚合后的统计结果)      │
  └────────────────────────────────────────────────────────┘

  例子:"在温度>60的设备里,统计每个车间的设备数,只看数量≥2的车间"

  SELECT department, COUNT(*)
  FROM devices
  WHERE temperature > 60        ← 先把温度≤60的行踢掉
  GROUP BY department
  HAVING COUNT(*) >= 2;         ← 分组后,把数量<2的车间踢掉

SQL 执行顺序(理解这个,从此不写错)

书写 的顺序 ≠ 数据库执行的顺序:

复制代码
  你写的顺序:                  数据库实际执行顺序:
  ─────────────                ─────────────────────
  SELECT  ...        ⑤         ① FROM + JOIN   先确定从哪些表拼数据
  FROM    ...        ①         ② WHERE         逐行过滤
  JOIN    ...        ①         ③ GROUP BY      分组
  WHERE   ...        ②         ④ HAVING        过滤分组
  GROUP BY ...       ③         ⑤ SELECT        确定输出哪些列/聚合
  HAVING  ...        ④         ⑥ ORDER BY      排序
  ORDER BY ...       ⑥         ⑦ LIMIT         截取前 N 行
  LIMIT   ...        ⑦

💡 这解释了一个经典坑:SELECT 里用 AS 平均温度 起的别名,WHERE 里不能用(WHERE 在 ② 执行,SELECT ⑤ 还没跑,别名还没诞生);但 ORDER BY ⑥ 可以用(那时别名已存在)。踩过一次就记住了。


📝 本课小结

知识点 一句话记住
拆表 消除数据重复,一处修改处处生效
主键 一行的唯一身份证(通常 id)
外键 指向别的表主键的列,是表间的桥
INNER JOIN 取交集,两边匹配上的才保留
LEFT JOIN 左表全保留,右边匹配不上补 NULL
三表 JOIN 就是连续做两次两表 JOIN
聚合函数 COUNT / SUM / AVG / MAX / MIN
GROUP BY 按某列分组,每组出一行统计
HAVING 分组后过滤组;WHERE 分组前过滤行
执行顺序 FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY→LIMIT
表别名 FROM devices d,多表时列名要带别名防歧义

🧠 核心认知:JOIN 是"横向拼列"(把分散在多表的字段拼到一行),GROUP BY 是"纵向压行"(把多行压成一行统计)。这两个方向搞清楚,多表查询就通了。


📋 课后练习

在 DBeaver SQL 编辑器里完成(先自己想,卡壳再翻笔记):

  1. 查每张工单的完整信息:工单号、标题、优先级、状态、设备名、上报人姓名(三表 JOIN)

  2. 按优先级统计工单数:高/中/低各有几张

  3. 按工程师统计:每人负责几台设备、所管设备的平均温度

  4. 找出"有高优先级工单"的设备名称(提示:WHERE priority='高')

  5. 找出"一张工单都没有"的设备(LEFT JOIN + IS NULL)

  6. 统计每个车间的工单总数,只显示工单数 > 0 的车间

  7. 按 status 分组统计工单数,并按数量从多到少排序

  8. 思考题:如果想查"上报工单最多的工程师是谁",需要哪几个 JOIN 和聚合?试着写出来


🔭 下节预告

今天的 JOIN + GROUP BY 已经能搞定现场 80% 的查询需求了。明天上点"硬菜"------窗口函数和 CTE

有个经典需求:"找出每个车间 温度最高的 2 台设备"。用 GROUP BY 做不到(一分组每个车间只剩一行,设备明细没了)。明天学的窗口函数能做到"不合并行,但每行都带着它所在组的排名",CTE 能把复杂查询拆成清晰的几段。这是从"会写 SQL"到"写得漂亮"的分水岭,咱们明天见真章!


🌍附录:前置课程列表

阶段一:

【FDE系列】阶段1Day 1:AI 层级关系 --- 四个嵌套的圈-CSDN博客

【FDE系列】阶段1Day 2:AI 三阶段发展史 --- 会认 → 会判断 → 会创造-CSDN博客

【FDE系列】阶段1Day 3:符号 AI vs 机器学习 --- 两条路线的本质区别-CSDN博客

【FDE系列】阶段1Day 4:Transformer 的历史意义 --- 2017 年的分水岭-CSDN博客

【FDE系列】阶段1Day 5:本周复习与自测 --- 检验你的 AI 认知地基-CSDN博客

【FDE系列】阶段1Day 6:Transformer 架构 --- 一张图纸盖出千千万万栋楼-CSDN博客

【FDE系列】阶段1Day 7:LLM 本质 --- 文字接龙机器-CSDN博客

【FDE系列】阶段1Day 8:Token --- 模型眼中的最小单位-CSDN博客

【FDE系列】阶段1Day 9:AI 幻觉 --- 为什么会一本正经地胡说八道-CSDN博客

【FDE系列】阶段1Day 10:上下文窗口 --- 模型的记忆力上限 + 本周复习-CSDN博客

【FDE系列】阶段1Day 11:Prompt --- 给模型立规矩-CSDN博客

【FDE系列】阶段1Day 12:Memory --- 让模型记住上下文

【FDE系列】阶段1Day 13:RAG --- 给模型配图书管理员-CSDN博客

【FDE系列】阶段1Day 14:Tool Use --- 让模型动手操作-CSDN博客

【FDE系列】阶段1Day 15:MCP --- 统一的工具接口标准 + 第三周复习-CSDN博客

【FDE系列】阶段1Day 16:什么是 FDE --- 把 AI 变成客户结果的人-CSDN博客

【FDE系列】阶段1Day 17:FDE vs 传统实施 --- 三大本质区别-CSDN博客

【FDE系列】阶段1Day 18:FDE 三重身份 + C6 胜任力模型-CSDN博客

【FDE系列】阶段1Day 19:七阶段行动路径 + 行业经验的价值-CSDN博客

【FDE系列】阶段1Day 20:阶段总结与产出物 --- 第一阶段收官-CSDN博客


阶段二:

【FDE系列】阶段2:Day 21:Python 环境搭建 --- 写出你的第一行代码-CSDN博客

【FDE系列】阶段2:Day 22:变量、数据类型、条件判断 --- Python 的"记忆"和"判断"-CSDN博客

【FDE系列】阶段2:Day 23:循环与函数 --- 让代码跑 100 遍、把逻辑打包复用-CSDN博客

【FDE系列】阶段2:Day 24:数据结构 --- 列表、字典、集合、元组-CSDN博客

【FDE系列】阶段2:Day 25:文件读写与 JSON --- 让程序连通外部数据(第一周收官)-CSDN博客

【FDE系列】阶段2:Day 26:模块化编程 --- 把代码拆成"抽屉柜"-CSDN博客

【FDE系列】阶段2:Day 27:异常处理与日志 --- 让程序"摔不烂、查得到"-CSDN博客

【FDE系列】阶段2:Day 28:FastAPI 入门 --- 把你的函数变成 API 服务-CSDN博客

【FDE系列】阶段2:Day 29:FastAPI 进阶 --- Pydantic 模型与完整 CRUD 实战-CSDN博客

【FDE系列】阶段2:Day 30:生产代码规范 --- 测试、类型注解、配置管理(第二周收官)-CSDN博客

【FDE系列】阶段2:Day 31:SQL 基础 --- 增删改查一把梭-CSDN博客

相关推荐
Ticnix1 小时前
迁移脚本能跑通,不代表你回滚得回来
后端·python
航飞光电市场经理1 小时前
UWB定位技术选型指南:从芯片架构到定位引擎的底层能力分析
大数据·人工智能·物联网·安全·人员定位
我的xiaodoujiao1 小时前
Django 基础知识详细图文教程 10-Django 模板引擎 3
后端·python·测试工具·django
quantdash_cc1 小时前
量化策略为什么需要实时行情数据?从信号产生到交易决策的时间差说起
开发语言·python·数据分析·量化交易·股票数据·quantdash
H Journey1 小时前
pip 和uv 开发和部署python项目
python·pip·uv
长谷深风1111 小时前
根因定位:三步隔离法破解AIBadcase
人工智能·ai·大模型·retrieval·ai智能体·aiagent·aibadcase
陈碧甫1 小时前
元龙因果链的因果生成式写作
人工智能
deepseek231 小时前
GPT-6 Astra 破解 FrontierMath 九年悬案拆解:调和熵投票规则反证核恒非空,局部搜索如何终结反例悬赏
人工智能·算法·ai agent
外收内放1 小时前
Python与AI应用(json模块)
python·学习