| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- -- =====================================================================================
- -- 1.0.517 · S1 · dwd_requirement_examine_detail 升级为「工单当前齐套/缺料」的中台权威表
- --
- -- 本表没有 SqlSugar 实体,也没有 UpdateScripts 里的 CREATE:
- -- 建表 DDL 内联在 server/Plugins/Admin.NET.Plugin.AiDOP/Order/S1MdpSyncTransformService.cs
- -- 的 EnsureS1RuntimeObjectsAsync()(CREATE TABLE IF NOT EXISTS)。
- -- ⇒ 新库由那段 DDL 一次建全,旧库由本脚本 ALTER 追加。两处必须同名同类型同顺序,否则新旧环境列序分叉。
- -- 本脚本的三个 ADD COLUMN 与该 DDL 里 update_time 之后的三列一一对应。
- --
- -- 本批变更:
- -- B1 新增 bom_level / material_role / is_current_flag + idx_req_exam_current
- -- B3 给齐套三量补「标准列」注释(不新增别名列、不重算,理由见下)
- -- B7 清理前修数据(理由见文件末尾)
- --
- -- ── B3:齐套三量的标准名 ────────────────────────────────────────────────────────────
- -- need_count / use_qty / lack_qty 就是本表「需求量 / 已满足量 / 缺口量」的标准列名。
- -- 不新增 required_qty / satisfied_qty / shortage_qty 别名列:别名 = 同一数字两个写入点,迟早对不上;
- -- 更不重算一套,那会造出与源系统不一致的第二口径。
- -- 恒等式 lack_qty + use_qty = need_count:实测 aidopdev 1019060/1019060 行全部成立,
- -- 最大绝对偏差 0.0000,三列均无 NULL ⇒ 该恒等式由源系统保证,可被下游直接依赖。
- -- =====================================================================================
- SET @tbl := (SELECT COUNT(*) FROM information_schema.TABLES
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'dwd_requirement_examine_detail');
- -- ── B1 · bom_level ───────────────────────────────────────────────────────────────────
- SET @sql := IF(
- @tbl = 1 AND (SELECT COUNT(*) FROM information_schema.COLUMNS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'dwd_requirement_examine_detail'
- AND COLUMN_NAME = 'bom_level') = 0,
- 'ALTER TABLE `dwd_requirement_examine_detail` ADD COLUMN `bom_level` INT NULL COMMENT ''BOM 层级 ← raw_data.$.level;1=成品根,>1=投入料''',
- 'DO 0');
- PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
- -- ── B1 · material_role ───────────────────────────────────────────────────────────────
- -- 仓库约定:流水线枚举一律 UPPER_SNAKE VARCHAR(对齐 denominator_status 等),中文只用于业务展示解码。
- SET @sql := IF(
- @tbl = 1 AND (SELECT COUNT(*) FROM information_schema.COLUMNS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'dwd_requirement_examine_detail'
- AND COLUMN_NAME = 'material_role') = 0,
- 'ALTER TABLE `dwd_requirement_examine_detail` ADD COLUMN `material_role` VARCHAR(32) NULL COMMENT ''物料角色枚举:FINISHED_GOOD_ROOT / INPUT_MATERIAL''',
- 'DO 0');
- PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
- -- ── B1 · is_current_flag ─────────────────────────────────────────────────────────────
- -- 仓库约定:布尔一律 `<noun>_flag TINYINT NOT NULL DEFAULT 0`(不用 is_* 裸名、不用 bit)。
- -- ⚠️ DEFAULT 0 同时承担 B7 的「失效」职责:本 ALTER 一落地,全部存量前修行立刻变成非当前,
- -- 不存在「旧批次仍被当作 current」的窗口。失效是 DDL 原子完成的,不依赖后面的 DELETE 是否跑完。
- SET @sql := IF(
- @tbl = 1 AND (SELECT COUNT(*) FROM information_schema.COLUMNS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'dwd_requirement_examine_detail'
- AND COLUMN_NAME = 'is_current_flag') = 0,
- 'ALTER TABLE `dwd_requirement_examine_detail` ADD COLUMN `is_current_flag` TINYINT NOT NULL DEFAULT 0 COMMENT ''1=属于当前快照批次;同一 (tenant, factory) 作用域内恒只有一个批次为 1''',
- 'DO 0');
- PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
- -- ── B1 · 支撑 (tenant_id, is_current_flag, morder_no) 的索引 ─────────────────────────
- -- 典型读法:WHERE tenant_id=? AND is_current_flag=1 AND morder_no=?(取某工单的当前缺料)。
- SET @sql := IF(
- @tbl = 1 AND (SELECT COUNT(*) FROM information_schema.STATISTICS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'dwd_requirement_examine_detail'
- AND INDEX_NAME = 'idx_req_exam_current') = 0,
- 'ALTER TABLE `dwd_requirement_examine_detail` ADD KEY `idx_req_exam_current` (`tenant_id`,`is_current_flag`,`morder_no`)',
- 'DO 0');
- PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
- -- ── B3 · 把「标准列」契约写进 schema,让任何 SHOW CREATE TABLE 的人都能看到 ───────────
- SET @sql := IF(
- @tbl = 1 AND (SELECT COUNT(*) FROM information_schema.COLUMNS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'dwd_requirement_examine_detail'
- AND COLUMN_NAME = 'need_count' AND COLUMN_COMMENT LIKE '标准列%') = 0,
- 'ALTER TABLE `dwd_requirement_examine_detail`
- MODIFY COLUMN `need_count` DECIMAL(18,4) NULL COMMENT ''标准列·需求量(齐套恒等式:lack_qty + use_qty = need_count)'',
- MODIFY COLUMN `use_qty` DECIMAL(18,4) NULL COMMENT ''标准列·已满足量(不要新增 satisfied_qty 别名)'',
- MODIFY COLUMN `lack_qty` DECIMAL(18,4) NULL COMMENT ''标准列·缺口量(不要新增 shortage_qty 别名)''',
- 'DO 0');
- PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
- -- =====================================================================================
- -- B7 · 清理前修数据
- --
- -- 【为什么必须清,而不是留着】
- -- 前修行是在缺少两道过滤的情况下生成的,成规模地错:
- -- ① 表头软删未过滤:贴源 b_examine_result 5969 行里 5851 行 IsDeleted 为真(仅 118 行存活)
- -- ⇒ 旧 DWD 约 98% 建立在已作废的核验单上,把作废单的缺料当成现行缺料。
- -- ② FULL 当成了追加:贴源 b_bom_child_examine 共 32105 行,最新全量批次只有 15272 行,
- -- 其余是源侧已删除的孤儿,却仍被算进 DWD。
- -- 叠加 uk(tenant_id,row_id,calc_batch_id) 的追加式累积,最终 1019060 行 / 3439 个批次全部不可信。
- --
- -- 【为什么不回填而是删除】
- -- material_role 对前修行没有可信来源:
- -- · DWD 自身从未物化过 level,回填只能反查贴源;
- -- · 而贴源 mdp_stg_so 的唯一键 uk_source_key=(source_system, source_table, source_biz_key) 不含批次,
- -- 每轮 FULL 会就地覆盖同一 biz_key 的 raw_data ⇒ 当年生成某个历史批次时所用的 raw_data 已经不存在了。
- -- · 强行用「今天的 level」去回填「历史批次」,等于给历史批次编造一个它当时并不具备的属性 —— 是伪造,不是修复。
- -- 且本表当前读者数为 0,删除不影响任何消费方;数据完全派生自贴源层(本脚本不动贴源),
- -- 下一轮 S1 跑批即可重建 ⇒ 删除在意图上是可逆的。
- --
- -- 【谓词为什么是 material_role IS NULL】
- -- 修复后的投影对 material_role 恒不产生 NULL(level 脏值/缺失一律落 INPUT_MATERIAL),
- -- ⇒ material_role IS NULL 精确等价于「前修行」。该谓词幂等、可重跑,
- -- 且若在 ALTER 与本 DELETE 之间恰好跑过一轮新管线,新产生的正确行不会被误删。
- -- =====================================================================================
- SET @sql := IF(
- @tbl = 1 AND (SELECT COUNT(*) FROM information_schema.COLUMNS
- WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'dwd_requirement_examine_detail'
- AND COLUMN_NAME = 'material_role') = 1,
- 'DELETE FROM `dwd_requirement_examine_detail` WHERE `material_role` IS NULL',
- 'DO 0');
- PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
- -- ── 回滚(注释,非可执行)──
- -- ALTER TABLE `dwd_requirement_examine_detail`
- -- DROP KEY `idx_req_exam_current`,
- -- DROP COLUMN `is_current_flag`, DROP COLUMN `material_role`, DROP COLUMN `bom_level`;
- -- 被删除的前修行不做回滚:其内容本身不可信,重建方式是重跑 S1 跑批。
|