我尝试执行许可证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)
答案 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