You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不同表多字段唯一匹配值计数的实现难题

问题:统计两表发票对的型号、物料唯一匹配数量

表结构说明

我有两张存储产品信息的表,包含字段:发票号(Num)、产品编码(Code)、厂商(Developer)、Brand、Model、Article,其中Brand和Article可能为NULL。

Table1 数据

+-------------+--------+-----------+-------+---------+---------+
| Num         | Code   | Developer | Brand | Model   | Article |
+-------------+--------+-----------+-------+---------+---------+
| 111/111/111 | 0803   | Dev1      | Bra1  | Mod1    | Art1    |
| 222/222/222 | 0706   | Dev2      | Bra2  | Mod2    | Art2    |
| 222/222/222 | 0706   | Dev2      | Bra2  | Mod2    | Art3    |
| 222/222/222 | 0706   | Dev2      | Bra2  | Mod3    | Art5    |
| 333/333/333 | 0717   | Dev3      | Bra3  | Mod4    | Art4    |
| 333/333/333 | 0717   | Dev3      | Bra3  | Mod4    | Art6    |
| 444/444/444 | 0805   | Dev1      | Bra1  | Mod1    | Art1    |
| 444/444/444 | 0805   | Dev1      | Bra1  | Mod1    | Art7    |
+-------------+--------+-----------+-------+---------+---------+

Table2 数据

+-------------+--------+-----------+-------+---------+---------+
| Num         | Code   | Developer | Brand | Model   | Article |
+-------------+--------+-----------+-------+---------+---------+
| 666/666/666 | 0803   | Dev1      | Bra1  | Mod1    | Art1    |
| 777/777/777 | 0706   | Dev2      | Bra2  | Mod7    | Art7    |
| 777/777/777 | 0706   | Dev2      | Bra2  | Mod7    | Art7    |
| 888/888/888 | 0717   | Dev3      | Bra2  | Mod4    | Art4    |
| 888/888/888 | 0717   | Dev3      | Bra3  | Mod4    | Art4    |
| 888/888/888 | 0717   | Dev3      | Bra3  | Mod8    | Art8    |
| 999/999/999 | 0805   | Dev1      | Bra1  | Mod1    | Art1    |
| 999/999/999 | 0805   | Dev1      | Bra1  | Mod1    | Art7    |
+-------------+--------+-----------+-------+---------+---------+

已完成的步骤

通过Code和Developer字段关联两表,使用listagg函数聚合Model、Article字段,得到以下结果:

+-------------+-------------+-----------+------------+------------+----------------+------------+
| Num_Tab1    | Num_Tab2    | Developer | Model_Tab1 | Model_Tab2 | Art_Tab1       | Art_Tab2   |
+-------------+-------------+-----------+------------+------------+----------------+------------+
| 111/111/111 | 666/666/666 | Dev1      | Mod1       | Mod1       | Art1           | Art1       |
| 222/222/222 | 777/777/777 | Dev2      | Mod2;Mod3  | Mod7       | Art2;Art3;Art5 | Art7       |
| 333/333/333 | 888/888/888 | Dev3      | Mod4       | Mod4;Mod8  | Art4;Art6      | Art4;Art8  |
| 444/444/444 | 999/999/999 | Dev1      | Mod1       | Mod1       | Art1;Art7      | Art1;Art7  |
+-------------+-------------+-----------+------------+------------+----------------+------------+

需求

需要为每对发票统计Model、Article的唯一匹配值数量,预期结果如下:

+-------------+-------------+------+------------+------------+----------------+------------+-------+-----+
| Num_Tab1    | Num_Tab2    | Dev  | Model_Tab1 | Model_Tab2 | Art_Tab1       | Art_Tab2   | Mod_c |Art_c|
+-------------+-------------+------+------------+------------+----------------+------------+-------+-----+
| 111/111/111 | 666/666/666 | Dev1 | Mod1       | Mod1       | Art1           | Art1       | 1     | 1   |
| 222/222/222 | 777/777/777 | Dev2 | Mod2;Mod3  | Mod7       | Art2;Art3;Art5 | Art7       | 0     | 0   |
| 333/333/333 | 888/888/888 | Dev3 | Mod4       | Mod4;Mod8  | Art4;Art6      | Art4;Art8  | 1     | 1   |
| 444/444/444 | 999/999/999 | Dev1 | Mod1       | Mod1       | Art1;Art7      | Art1;Art7  | 1     | 2   | 
+-------------+-------------+------+------------+------------+----------------+------------+-------+-----+

尝试过的方法及问题

  • 使用regexp_count():将一个表的聚合字段拆分为匹配模式(用|分隔),统计另一个表字段中的匹配数。但发票条目过多时,会触发**ORA-12733(正则表达式过长)**错误。
  • 子查询关联统计:尝试在主查询中嵌入子查询统计Model匹配数,但因未关联外部发票号,导致报错或结果不符合预期。
  • 子查询放入FROM子句:调整结构后仍无法得到正确的匹配计数。

解决方案

方法1:利用集合类型统计交集数量

先对每个发票的Model、Article去重,存储为集合类型,再统计两个集合的交集元素数:

WITH tab1_unique AS (
    SELECT 
        Num AS Num_Tab1,
        Code,
        Developer,
        LISTAGG(DISTINCT Model, ';') WITHIN GROUP (ORDER BY Model) AS Model_Tab1,
        LISTAGG(DISTINCT Article, ';') WITHIN GROUP (ORDER BY Article) AS Art_Tab1,
        COLLECT(DISTINCT Model) AS model_set_tab1,
        COLLECT(DISTINCT Article) AS article_set_tab1
    FROM Table1
    GROUP BY Num, Code, Developer
),
tab2_unique AS (
    SELECT 
        Num AS Num_Tab2,
        Code,
        Developer,
        LISTAGG(DISTINCT Model, ';') WITHIN GROUP (ORDER BY Model) AS Model_Tab2,
        LISTAGG(DISTINCT Article, ';') WITHIN GROUP (ORDER BY Article) AS Art_Tab2,
        COLLECT(DISTINCT Model) AS model_set_tab2,
        COLLECT(DISTINCT Article) AS article_set_tab2
    FROM Table2
    GROUP BY Num, Code, Developer
)
SELECT 
    t1.Num_Tab1,
    t2.Num_Tab2,
    t1.Developer AS Dev,
    t1.Model_Tab1,
    t2.Model_Tab2,
    t1.Art_Tab1,
    t2.Art_Tab2,
    (SELECT COUNT(*) 
     FROM TABLE(t1.model_set_tab1) m1 
     JOIN TABLE(t2.model_set_tab2) m2 ON m1.COLUMN_VALUE = m2.COLUMN_VALUE) AS Mod_c,
    (SELECT COUNT(*) 
     FROM TABLE(t1.article_set_tab1) a1 
     JOIN TABLE(t2.article_set_tab2) a2 ON a1.COLUMN_VALUE = a2.COLUMN_VALUE) AS Art_c
FROM tab1_unique t1
JOIN tab2_unique t2 ON t1.Code = t2.Code AND t1.Developer = t2.Developer
ORDER BY t1.Num_Tab1;

方法2:基于去重后的明细关联统计

先提取每个发票的唯一Model和Article,再通过关联统计交集数量,同时完成聚合:

WITH tab1_unique AS (
    SELECT DISTINCT Num AS Num_Tab1, Code, Developer, Model, Article
    FROM Table1
),
tab2_unique AS (
    SELECT DISTINCT Num AS Num_Tab2, Code, Developer, Model, Article
    FROM Table2
)
SELECT 
    t1.Num_Tab1,
    t2.Num_Tab2,
    t1.Developer AS Dev,
    LISTAGG(DISTINCT t1.Model, ';') WITHIN GROUP (ORDER BY t1.Model) AS Model_Tab1,
    LISTAGG(DISTINCT t2.Model, ';') WITHIN GROUP (ORDER BY t2.Model) AS Model_Tab2,
    LISTAGG(DISTINCT t1.Article, ';') WITHIN GROUP (ORDER BY t1.Article) AS Art_Tab1,
    LISTAGG(DISTINCT t2.Article, ';') WITHIN GROUP (ORDER BY t2.Article) AS Art_Tab2,
    COUNT(DISTINCT CASE WHEN t1.Model = t2.Model THEN t1.Model END) AS Mod_c,
    COUNT(DISTINCT CASE WHEN t1.Article = t2.Article THEN t1.Article END) AS Art_c
FROM tab1_unique t1
JOIN tab2_unique t2 ON t1.Code = t2.Code AND t1.Developer = t2.Developer
GROUP BY t1.Num_Tab1, t2.Num_Tab2, t1.Developer
ORDER BY t1.Num_Tab1;

方案说明

  • 两种方法均从原始明细数据出发,先去重再处理,避免了先聚合后拆分的长度限制问题。
  • 方法1利用Oracle集合类型存储唯一值,通过集合交集统计匹配数;方法2直接在关联后的明细中用条件计数统计交集,逻辑更直观。

内容的提问来源于stack exchange,提问作者Roman Lukyanov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 16:54:51