产品下线也不容易

        产品在经历了漫长的研发阶段以后上线,面临着各方真实的环境和用户,其实是很难的一件事情。但产品在经历了漫长的运营以后决定下线,面临着庞大的用户数据和部分忠实的粉丝,也一样是一件不容易的事情。


        首先要做的就是制定一个详细的下线方案了,具体包括:
        减少或禁止新增用户及新增数据,如果一边下线一边有新增数据,总不是一件易于处理的事情,既然已经决定下线,那就把写数据的功能入口关闭了吧。
        用户通知机制及时间点,面对着用户,尤其是忠实用户,虽然于心不忍,但如果能近早的通知到,多少总是能有所慰藉。
        用户数据处理,长期运营积累下来的用户数据对系统而言可能没用了,但对用户而言依然重要且有价值,因此得为用户提供数据导出的功能,帮用户做好数据管理和导出工作。
        服务分阶段降级及数据清理。根据计划分阶段降级服务,减少运维成本,对数据进行妥善的清理工作。

        有了详细的方案以后,就是 用户公告的发布了,找PR高手、文案高手来吧,远比冷冰冰的字眼更能温暖人心,虽然这个产品下线了,但用户也许还是公司的用户。

        下线表明的也是一种态度,忍着痛也要做好,为用户,也为自己。

——欢迎转载,请注明原文出处  http://blog.youkuaiyun.com/caowenbin  ——
——欢迎关注微信号“曹文斌的软件思考”,共同探讨软件人生——

WITH -- 第一步:获取计划信息,并判断是 Queen 还是 300works(IUI)下线 PLAN_DATA AS ( -- 原始数据 SELECT B.TECHNOLOGY TECH, A.productid PROD, 'IUI Start' REMARK FROM DR01.SDB_TB_FABCITE_CREATELOT A LEFT JOIN (SELECT UNIQUE PRODUCTNAME, TECHNOLOGY FROM SDB_TB_INFO_PRODUCT) B ON A.productid = B.PRODUCTNAME WHERE A.productid NOT LIKE 'XP%' UNION ALL -- 新增的虚拟行 SELECT '48NOR' AS TECH, '0A7K' AS PROD, 'Manual Input' AS REMARK FROM DUAL ), -- 第二步:获取 PROD 与 ZEROPRODUCT 映射(MES/IUI) T1 AS ( SELECT * FROM ( -- MES 中的映射 SELECT 'MES' SOURCE, a.TECHNOLOGY, PROD, STARTMATERIAL, ZEROPRODUCT, SUM(STARTQTY) AS TOTAL_STARTQTY FROM ( SELECT TECHNOLOGY, SUBSTR(PRODUCTNAME, 1, 4) AS PROD, STARTMATERIAL, ZEROPRODUCT, STARTQTY FROM BJTYS.SDB_TB_INFO_PRODUCT WHERE STARTQTY > 0 ) a GROUP BY a.TECHNOLOGY, PROD, STARTMATERIAL, ZEROPRODUCT UNION ALL -- IUI 中的映射 SELECT 'IUI' SOURCE, a.TECHNOLOGY, PROD, STARTMATERIAL, ZEROPRODUCT, SUM(STARTQTY) AS TOTAL_STARTQTY FROM ( SELECT TECHNOLOGY, SUBSTR(PRODUCTNAME, 1, 4) AS PROD, STARTMATERIAL, ZEROPRODUCT, STARTQTY FROM DW01.SDB_TB_INFO_PRODUCT_P1@B2MFGDBP1 WHERE STARTQTY > 0 ) a GROUP BY a.TECHNOLOGY, PROD, STARTMATERIAL, ZEROPRODUCT ) ), -- 第三步:获取当前库存中 LOT 的 MATERIALNO 信息(EX/EY 和 SOURCEE*) T2 AS ( SELECT UNIQUE AA.*, BB.foupid, CC.Plocation, CASE WHEN SubStr(AA.lotid, 2, 1) IN ('X', 'Y') THEN 'ZeroFlow' WHEN SubStr(AA.lotid, 1, 6) = 'SOURCE' THEN 'RawMaterial' ELSE '' END AS CAT FROM ( -- EX/EY 库存物料 SELECT A.lotid, A.componentqty QTY, A.status, A.productname PROD, B.vendorid VENDOR, B.comsumedmaterial materialno, SubStr(b.inventoryid, 2, Length(b.inventoryid)) wafertype, B.parentid, B.qty parentqty, A.startdate || ' ' || A.starttime starttime FROM dw01.sdb_tb_wip_ship_P1@B2MFGDBP1 A LEFT JOIN DW01.sdb_tb_inventory_lot_infor_P1@B2MFGDBP1 B ON SUBSTR(A.LOTID, 1, 8) = SUBSTR(B.LOTID, 1, 8) WHERE SubStr(A.lotid, 1, 2) IN ('EX', 'EY') AND status = 'Inventory' UNION ALL -- SOURCEE* 原材料 SELECT source_lot LOTID, componentqty QTY, 'Inventory' STATUS, sourceprod PROD, vendorid VENDOR, material_no materialno, wafertype, vendorlotid parentid, componentqty parentqty, createdatetime STARTTIME FROM dw01.rpt_ms_source_lot_material_info@b2mfgdbp1 WHERE SubStr(source_lot, 1, 7) = 'SOURCEE' ) AA LEFT JOIN ( SELECT foupid, lotid FROM DW01.sdb_tb_smic_foup_slotmap_P1@B2MFGDBP1 ) BB ON AA.LOTID = BB.LOTID LEFT JOIN ( SELECT foupid, location Plocation FROM DW01.sdb_tb_smic_foup_P1@B2MFGDBP1 ) CC ON BB.FOUPID = CC.FOUPID WHERE CC.Plocation IS NULL OR SubStr(CC.plocation, 1, 2) IN ('ES','EB','FS','FB','GS','GB','2S','US','UB') ) -- 主查询:串联三张表,并应用 VENDOR 过滤规则 SELECT DISTINCT P.TECH, P.PROD, -- 原始计划产品 T1.TECHNOLOGY AS MASTER_TECH, T1.PROD AS MASTER_PROD, -- 大 flow 主产品(通常和 PLAN_PROD 一致) T1.ZEROPRODUCT, T2.PROD AS CURRENT_MATCHED_PROD, -- 实际匹配到的 PROD(如 XPE00800120BNA1) T2.MATERIALNO, T2.VENDOR FROM PLAN_DATA P JOIN T1 ON SUBSTR(P.PROD, 1, 4) = T1.PROD JOIN T2 ON (T1.ZEROPRODUCT = T2.PROD OR (T1.ZEROPRODUCT = 'XPE00800120BN' AND T2.PROD = 'XPE00800120BNA1')) WHERE T2.vendor in (SELECT vendor FROM dr01.sdb_tb_wfs_vendors_constraint WHERE prod=P.prod) ORDER BY P.TECH DESC, P.PROD, T1.ZEROPRODUCT, T2.MATERIALNO; 我唯一的改动是WHERE T2.vendor in (SELECT vendor FROM dr01.sdb_tb_wfs_vendors_constraint WHERE prod=P.prod)我想从得到的结果中筛掉vendors constraint表中能用的vendor
最新发布
12-13
你的改动: ```sql WHERE T2.vendor IN (SELECT vendor FROM dr01.sdb_tb_wfs_vendors_constraint WHERE prod = P.prod) ``` 意图是:**根据 `P.PROD` 找到允许使用的 vendor 列表,过滤掉在白名单中的记录。** 这个逻辑本身没有问题,但正是这个子查询导致了你之前没报错、现在报 **ORA-00918: column ambiguously defined** 的原因。 --- ## 🔍 为什么加了这行就报 ORA-00918? ### ❌ 根本原因: > 在 `WHERE` 子句的关联子查询中,使用了外部查询的字段 `P.PROD`,而 `P.PROD` 和内部表 `dr01.sdb_tb_wfs_vendors_constraint` 的 `PROD` 字段同名 —— 当 Oracle 解析整个查询计划时,尤其是在多层 `WITH` + `UNION` 结构下,**列名歧义会被提前触发**,即使主查询写了别名! 更关键的是: 👉 **`dr01.sdb_tb_wfs_vendors_constraint` 表中的 `PROD` 字段与 CTE 中的 `PROD` 同名**,优化器在解析视图展开时无法分辨哪个 `PROD` 属于哪个作用域,从而抛出 ORA-00918。 --- ## ✅ 正确写法建议(解决歧义 + 提高性能) ### ✅ 方法一:【推荐】将 vendor 约束提前 JOIN,避免相关子查询 ```sql -- 主查询:改为 JOIN 方式,明确列引用 SELECT DISTINCT P.TECH, P.PROD, T1.TECHNOLOGY AS MASTER_TECH, T1.PROD AS MASTER_PROD, T1.ZEROPRODUCT, T2.PROD AS CURRENT_MATCHED_PROD, T2.MATERIALNO, T2.VENDOR FROM PLAN_DATA P JOIN T1 ON SUBSTR(P.PROD, 1, 4) = T1.PROD JOIN T2 ON (T1.ZEROPRODUCT = T2.PROD OR (T1.ZEROPRODUCT = 'XPE00800120BN' AND T2.PROD = 'XPE00800120BNA1')) -- 改为 LEFT JOIN + IS NOT NULL 模式,或直接 INNER JOIN 匹配有效的 vendor JOIN dr01.sdb_tb_wfs_vendors_constraint V ON V.PROD = P.PROD AND V.VENDOR = T2.VENDOR -- 明确匹配 ORDER BY P.TECH DESC, P.PROD, T1.ZEROPRODUCT, T2.MATERIALNO; ``` ✅ 优势: - 避免相关子查询(correlated subquery),性能更好 - 所有列都有明确来源表前缀,消除歧义 - 更容易被 CBO 优化执行计划 --- ### ✅ 方法二:保留原写法,但给子查询加别名防止混淆 如果你坚持用 `IN (SELECT ...)`,请确保: 1. 给子查询中的列起别名 2. 明确指定外层引用 ```sql WHERE T2.VENDOR IN ( SELECT vc.VENDOR FROM dr01.sdb_tb_wfs_vendors_constraint vc WHERE vc.PROD = P.PROD -- 明确 vc.PROD vs P.PROD ) ``` 但这仍可能因底层列映射模糊而出错(尤其当 `vc.PROD` 和 `P.PROD` 被视为同名列合并)。 --- ## 🛠️ 进阶建议:检查并重命名冲突列 为了彻底避免 ORA-00918,在所有 `WITH` 子句中都应避免使用通用列名如 `PROD`, `TECH`, `VENDOR`。 ### 示例:安全命名风格 ```sql PLAN_DATA AS ( SELECT B.TECHNOLOGY AS PLAN_TECH, A.productid AS PLAN_PROD, 'IUI Start' AS REMARK ... ), T1 AS ( SELECT SOURCE, TECHNOLOGY AS MAP_TECH, PROD AS MAP_PROD, ZEROPRODUCT AS ZERO_PROD, STARTMATERIAL AS RAW_MATERIAL, TOTAL_STARTQTY ... ), T2 AS ( SELECT LOTID, QTY, STATUS, PROD AS LOT_PROD, VENDOR AS SUPPLIER, MATERIALNO, ... ) ``` 然后主查询中全部使用清晰命名: ```sql WHERE T2.SUPPLIER IN ( SELECT VENDOR FROM dr01.sdb_tb_wfs_vendors_constraint WHERE PROD = P.PLAN_PROD ) ``` 这样能极大降低列歧义风险。 --- ## ✅ 总结:如何修复你的 ORA-00918 | 问题 | 解决方案 | |------|----------| | `PROD` 多处同名导致列歧义 | 给每个字段加唯一别名(如 `PLAN_PROD`, `ZERO_PROD`) | | 相关子查询引用外部列引发解析错误 | 改为 `JOIN` 或确保子查询完全去歧义 | | `SELECT *` 在 `UNION ALL` 中危险 | 改为显式列出所有字段 | --- ## ✅ 推荐最终修改片段(关键部分) ```sql -- 主查询改写为 JOIN 形式(推荐) SELECT DISTINCT P.TECH, P.PROD, T1.TECHNOLOGY AS MASTER_TECH, T1.PROD AS MASTER_PROD, T1.ZEROPRODUCT, T2.PROD AS CURRENT_MATCHED_PROD, T2.MATERIALNO, T2.VENDOR FROM PLAN_DATA P JOIN T1 ON SUBSTR(P.PROD, 1, 4) = T1.PROD JOIN T2 ON (T1.ZEROPRODUCT = T2.PROD OR (T1.ZEROPRODUCT = 'XPE00800120BN' AND T2.PROD = 'XPE00800120BNA1')) JOIN dr01.sdb_tb_wfs_vendors_constraint VC ON VC.PROD = P.PROD AND VC.VENDOR = T2.VENDOR ORDER BY P.TECH DESC, P.PROD, T1.ZEROPRODUCT, T2.MATERIALNO; ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文斌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值