递归sql赋值直到数量耗尽

时间:2013-02-28 14:44:44

标签: sql db2

我尝试执行许可证ID号的递归连接分配,直到数量“耗尽”使用CTE样式,联合所有递归语句,但我无法完全协同工作。

我一直遇到的问题是许多许可证可以覆盖1个实例,所以当我加入许可证表时,我会得到很多行。任何建议都是最受欢迎的。

TABLE: INSTALLEDSW      
INSTALLEDSW_ID  PRODUCT_ID  PRODUCT_NAME
200             1000        MY SOFTWARE
201             1000        MY SOFTWARE
202             1000        MY SOFTWARE
203             1000        MY SOFTWARE
204             1000        MY SOFTWARE
205             1000        MY SOFTWARE
206             1000        MY SOFTWARE
207             1000        MY SOFTWARE
208             1000        MY SOFTWARE


TABLE:  LICENSE          
LICENSE_ID  PRODUCT_ID  LICENSE_NAME    QUANTITY
100         1000        MY LICENSE      1 
101         1000        MY LICENSE      5 
102         1000        MY LICENSE      1


Desired Result Set  
INSTALLEDSW_ID      LICENSE_ID
200                 100
201                 101
202                 101
203                 101
204                 101
205                 101
206                 102
207                 (null)
208                 (null)

2 个答案:

答案 0 :(得分:1)

您不需要递归CTE。相反,您需要许可证的累积总和才能获得数量范围。最终的结果就是之后的联接。

我假设您正在使用支持此功能的Postgres,SQL Server 2012或Oracle。在其他数据库中,您可以执行必要的计算相关子查询而不是窗口函数。

select l.*, SumQTy - Qty + 1 as StartQTY, QTY as EndQTY
from (select l.*,
             sum(quantity) over (partition by product_id order by license_id) as Sumqty
      from license l
     ) l

因此,此许可证是StaartQTY和EndQTY之间的有效许可证。

接下来,您需要将这些应用于您的用户。为此,我们使用row_number()枚举已安装的:

with l as (
     select l.*, SumQTy - Qty + 1 as StartQTY, QTY as EndQTY
     from (select l.*,
                  sum(quantity) over (partition by product_id order by license_id) as Sumqty
           from license l
          ) l
    )
select i.installedsw_id, l.licence_id
from (select i.*,
             row_number() over (partition by product_id order by installedsw_id) as num
      from installedsw i
     ) i left outer join
     l
     on i.installedsw_id = l.installedsw_id and
        i.num between l.startQty and l.endQty

答案 1 :(得分:0)

尽可能避免递归,并且就此而言,累积总和(它们非常昂贵)。让自己成为一个整数表(经常使用的“工具刀”):

CREATE TABLE integers (n smallint primary key clustered)
INSERT integers SELECT TOP 1000 row_number() over (order by o.id) from sysobjects o cross join sysobjects

当你:

时,这会变得更容易
   join (select * from LICENSE, integers where n <= quantity) LICENSE on...

然后对每个表进行排名,加入排名,并在排名&lt; = #ofLicenses时设置License_ID。 (我不熟悉DB2,但您可能必须模拟临时表中的排名。)

SELECT ISW.INSTALLEDSW_ID, LICENSE_ID = case when LIC.rank <= [# of licenses] then LIC.LICENSE_ID else null end
FROM (     select *, rank = row_number over (order by INSTALLEDSW_ID) from INSTALLEDSW) ISW
    JOIN ( select *, rank = row_number over (order by LICENSE_ID)
           from (select * from LICENSE, integers where n <= quantity) t ) LIC on LIC.productid_id = ISW.productid AND LIC.rank = ISW.rank