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 に答える