Sql 如何在oracle中找到最接近的子集和

Sql 如何在oracle中找到最接近的子集和,sql,oracle,Sql,Oracle,我有两张桌子: 1) 其中之一是发票,有成千上万的数据。在我的发票表中,有客户的发票及其价格。 2) 另一个是债务。在我的债务表中,有每个客户发票的总债务。 我的目标是找到最接近的金额和债务的发票。例如,我有以下表格: 债务表: CUSTOMER_ID TOTAL_DEBTS 3326660 444$ 2789514 165$ 4931541

我有两张桌子: 1) 其中之一是发票,有成千上万的数据。在我的发票表中,有客户的发票及其价格。 2) 另一个是债务。在我的债务表中,有每个客户发票的总债务。
我的目标是找到最接近的金额和债务的发票。例如,我有以下表格:

债务表:

    CUSTOMER_ID         TOTAL_DEBTS
      3326660                444$      
      2789514                165$     
      4931541                121$ 
CUSTOMER_ID       INVOICE_ID        AMOUNT_OF_INVOICE
  3326660              1a                   157$ 
  3326660              1b                   112$ 
  3326660              1c                   10$ 
  3326660              1d                   94$ 
  3326660              1e                   47$ 
  3326660              1f                   35$ 
  3326660              1g                   14$ 
  3326660              1h                   132$ 
  3326660              1i                   8$ 
  3326660              1j                   60$ 
  3326660              1k                   42$ 
  2789514              2a                   86$ 
  2789514              2b                   81$
  2789514              2c                   99$
  2789514              2d                   61$
  2789514              2e                   16$
  2789514              2f                   83$
  4931541              3a                   11$
  4931541              3b                   14$
  4931541              3c                   17$
  4931541              3d                   121$
  4931541              3e                   35$
  4931541              3f                   29$
CUSTOMER_ID        TOTAL_DEBTS     CALCULATED_AMOUNT        INVOICES_ID   
  3326660              444$              444$              1a,1b,1f,1h,1i    
  2789514              165$              164$                   2b,2f
  4931541              121$              121$                    3d
发票表:

    CUSTOMER_ID         TOTAL_DEBTS
      3326660                444$      
      2789514                165$     
      4931541                121$ 
CUSTOMER_ID       INVOICE_ID        AMOUNT_OF_INVOICE
  3326660              1a                   157$ 
  3326660              1b                   112$ 
  3326660              1c                   10$ 
  3326660              1d                   94$ 
  3326660              1e                   47$ 
  3326660              1f                   35$ 
  3326660              1g                   14$ 
  3326660              1h                   132$ 
  3326660              1i                   8$ 
  3326660              1j                   60$ 
  3326660              1k                   42$ 
  2789514              2a                   86$ 
  2789514              2b                   81$
  2789514              2c                   99$
  2789514              2d                   61$
  2789514              2e                   16$
  2789514              2f                   83$
  4931541              3a                   11$
  4931541              3b                   14$
  4931541              3c                   17$
  4931541              3d                   121$
  4931541              3e                   35$
  4931541              3f                   29$
CUSTOMER_ID        TOTAL_DEBTS     CALCULATED_AMOUNT        INVOICES_ID   
  3326660              444$              444$              1a,1b,1f,1h,1i    
  2789514              165$              164$                   2b,2f
  4931541              121$              121$                    3d
我的目标表是:

    CUSTOMER_ID         TOTAL_DEBTS
      3326660                444$      
      2789514                165$     
      4931541                121$ 
CUSTOMER_ID       INVOICE_ID        AMOUNT_OF_INVOICE
  3326660              1a                   157$ 
  3326660              1b                   112$ 
  3326660              1c                   10$ 
  3326660              1d                   94$ 
  3326660              1e                   47$ 
  3326660              1f                   35$ 
  3326660              1g                   14$ 
  3326660              1h                   132$ 
  3326660              1i                   8$ 
  3326660              1j                   60$ 
  3326660              1k                   42$ 
  2789514              2a                   86$ 
  2789514              2b                   81$
  2789514              2c                   99$
  2789514              2d                   61$
  2789514              2e                   16$
  2789514              2f                   83$
  4931541              3a                   11$
  4931541              3b                   14$
  4931541              3c                   17$
  4931541              3d                   121$
  4931541              3e                   35$
  4931541              3f                   29$
CUSTOMER_ID        TOTAL_DEBTS     CALCULATED_AMOUNT        INVOICES_ID   
  3326660              444$              444$              1a,1b,1f,1h,1i    
  2789514              165$              164$                   2b,2f
  4931541              121$              121$                    3d
因为我的表中有成千上万的数据,所以性能对我来说非常重要。我从stackoverflow中找到代码:

但是,性能很低。当我发现Calculated_amount和total_debts之间的值相同时,我必须停止加法循环

谢谢你的帮助

使用递归查询:

with 
    t1 as ( 
        select customer_id cid, total_debts dbt, invoice_id iid, amount_of_invoice amt, 
               row_number() over (partition by customer_id order by invoice_id) rn
          from debts d join invoices i using (customer_id) ),
    t2 (cid, iid, ams, dbt, amt, sma, rn) as ( 
        select cid, cast(iid as varchar2(4000)), cast(amt as varchar2(4000)), 
               dbt, amt, amt, rn
          from t1 
        union all 
        select t2.cid, 
               t2.iid || ', ' || t1.iid,
               t2.ams || ', ' || t1.amt,
               t2.dbt, t2.amt, t1.amt + t2.sma, t1.rn
          from t2 
          join t1 on t1.cid = t2.cid and t1.rn > t2.rn and t2.sma + t1.amt <= t1.dbt),
    t3 as (
        select t2.*, rank() over (partition by cid order by dbt - sma ) rnk
          from t2)
select cid, iid, ams, dbt, sma from t3 where rnk = 1
子查询
T1
连接两个表并添加列
rn
,该列用于合并数据<代码>T2是分层的,它完成了工作的主要部分-合并所有数据,直到总和达到债务
T3
使用函数
rank
筛选最佳解决方案。如您所见,对于
CID
3326660,有四种最佳组合


请注意,对于大量数据,递归子查询速度很慢,并且此解决方案无法工作

对于SQL来说,这不是一个合适的问题。你需要概括所有可能的组合,看看哪一个最接近。同意@GordonLinoff,读一下这篇文章,它有助于你理解你的问题是关于什么的