2013-02-28 5 views
3

Я пытаюсь выполнить рекурсивное присвоение соединения идентификационным номерам лицензий до тех пор, пока количество «не закончится» с использованием стиля CTE, объединение всего рекурсивного оператора, но я не могу полностью заставить 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

+0

Таблицы INSTALLEDSW и LICENSE объединяются с помощью ПРОИЗВОДСТВА. Таким образом, в основном LICENSE.PRODUCTID говорит, что «эта лицензия может охватывать продукт XYZ». – user1527312

ответ

1

Вам не нужно рекурсивное ОТВ для этого. Вместо этого вам нужна общая сумма лицензий для получения диапазонов количеств. Конечным результатом является просто объединение после этого.

Предположим, вы используете 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

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... 

Тогда ранг каждой таблицы, объединение по рангу , и установите License_ID, когда rank < = #ofLicenses. (Я не знаком с 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/temp для этого? – user1527312

+0

@bwperrin. , , Почему, по вашему мнению, суммарные суммы дороже, чем 'row_number()'? В базах данных, которые поддерживают их с помощью оконных функций, производительность должна быть почти одинаковой. –

+0

@ user1527312 - вы можете использовать простой рекурсивный CTE для создания таблицы чисел «на лету». –

Смежные вопросы