3

我正在尝试使用 CTE 样式执行许可证 ID 号的递归连接分配,直到数量“用完”,联合所有递归语句,但我不能完全让这些部件一起工作。

我一直遇到的问题是许多许可证可以覆盖 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)
4

2 回答 2

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
于 2013-02-28T14:57:02.293 回答
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...

然后对每个表进行排名,加入排名,并在排名 <= #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
于 2013-02-28T14:54:58.173 回答