移除WITH子句后SQL出现笛卡尔积,结果不符求助
嘿,我一眼就看到问题出在哪了——你不必要地重复引用了mtl_system_items_b_kfv和mtl_system_items_tl这两个表,却没给重复的表之间加关联条件,直接触发了笛卡尔积,这才导致行数暴增到84万。
你的原WITH查询逻辑拆解
原来的WITH子句其实就是做了一件事:将mtl_system_items_b_kfv(物料主表的基表视图)和mtl_system_items_tl(多语言描述表)通过inventory_item_id和organization_id这两个主键做内连接,获取物料的基础信息+多语言描述。这个逻辑本身很简单,完全不需要重复引用表。
修正后的查询(移除WITH子句,保留原逻辑)
你只需要把WITH里的子查询直接放到主查询中即可,不需要额外加重复的表别名:
SELECT k.inventory_item_id AS inventory_item_id, k.organization_id AS organization_id, k.primary_uom_code AS primary_uom_code, k.concatenated_segments AS concatenated_segments, t.description AS description, t.language AS language FROM mtl_system_items_b_kfv k INNER JOIN mtl_system_items_tl t ON k.inventory_item_id = t.inventory_item_id AND k.organization_id = t.organization_id;
如果你习惯用旧的隐式连接语法(虽然更推荐显式JOIN,可读性更强),也可以写成:
SELECT k.inventory_item_id AS inventory_item_id, k.organization_id AS organization_id, k.primary_uom_code AS primary_uom_code, k.concatenated_segments AS concatenated_segments, t.description AS description, t.language AS language FROM mtl_system_items_b_kfv k, mtl_system_items_tl t WHERE k.inventory_item_id = t.inventory_item_id AND k.organization_id = t.organization_id;
为什么你的第二个查询会出错?
你添加了k1(重复的mtl_system_items_b_kfv)和t1(重复的mtl_system_items_tl),但没有在k和k1、t和t1之间添加关联条件(比如k.inventory_item_id = k1.inventory_item_id AND k.organization_id = k1.organization_id)。数据库会默认把k的每一行和k1的每一行做交叉匹配,t的每一行和t1的每一行做交叉匹配,最终行数就是k的行数 * k1的行数 * t的行数 * t1的行数,这就是典型的笛卡尔积,结果自然和原查询完全不符。
验证结果
执行上面的修正查询后,你可以用COUNT(*)验证行数:
SELECT COUNT(*) FROM mtl_system_items_b_kfv k INNER JOIN mtl_system_items_tl t ON k.inventory_item_id = t.inventory_item_id AND k.organization_id = t.organization_id;
这个结果应该和你原WITH查询的65000行完全一致。
内容的提问来源于stack exchange,提问作者Shruti sharma

