2013-02-28 181 views
3

我嘗試執行遞歸連接分配的許可證ID號,直到數量「用完」使用CTE樣式,union所有遞歸語句,但我無法完全讓peices工作一起。遞歸sql分配,直到數量耗盡

我一直遇到的問題是,許多許可證可以覆蓋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) 
+1

請問您能否顯示不太合適的查詢? – 2013-02-28 14:47:37

+1

'installedsw'和'license'表有什麼關係?只是通過'product_id'? 'INSTALLEDSW_ID'與'LICENSE_ID'有什麼關係? – Taryn 2013-02-28 14:50:59

+0

PRODUCTID加入了INSTALLEDSW和LICENSE表。所以基本上LICENSE.PRODUCTID說'這個許可證可以覆蓋產品XYZ'。 – user1527312 2013-02-28 14:52:35

回答

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 
+0

這個作品,謝謝戈登! – user1527312 2013-02-28 17:59:17

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 
+0

不幸的是,創建一個新表格不適合我。我可以使用CTE表/臨時表嗎? – user1527312 2013-02-28 15:32:56

+0

@bwperrin。 。 。爲什麼你認爲累計總和比'row_number()'貴?在使用窗口函數支持它們的數據庫中,性能應該非常接近相同。 – 2013-02-28 15:47:09

+0

@ user1527312 - 您可以使用簡單的遞歸CTE創建一個即時數字表。 – 2013-02-28 17:29:27