Try this...
I was able to implement this using recursive CTE
, all in 1 single SQL statement
The only assumption I had was that the Bucket and Item data set are sorted.
DECLARE @BUCKET TABLE
(
BUCKETID INT
, SIZE INT
)
DECLARE @ITEM TABLE
(
ITEMID INT
, SIZE INT
)
;
INSERT INTO @BUCKET
SELECT 1,2 UNION ALL
SELECT 2,2 UNION ALL
SELECT 3,2 UNION ALL
SELECT 4,4 UNION ALL
SELECT 5,4 UNION ALL
SELECT 6,7 UNION ALL
SELECT 7,9 UNION ALL
SELECT 8, 11 UNION ALL
SELECT 9, 11 UNION ALL
SELECT 10,12
INSERT INTO @ITEM
SELECT 1,2 UNION ALL
SELECT 2,2 UNION ALL
SELECT 3,5 UNION ALL
SELECT 4,11 UNION ALL
SELECT 5,12;
WITH TOTAL_BUCKETS
AS (
SELECT MAX(BUCKETID) CNT
FROM @BUCKET
) -- TO GET THE TOTAL BUCKETS COUNT TO HALT THE RECURSION
, CTE
AS (
--INVOCATION PART
SELECT BUCKETID
, (
SELECT MIN(ITEMID)
FROM @ITEM I2
WHERE I2.SIZE <= (
SELECT SIZE
FROM @BUCKET
WHERE BUCKETID = (1)
)
) ITEMID --PICKS THE FIRST ITEM ID MATCH FOR THE BUCKET SIZE
, BUCKETID + 1 NEXT_BUCKETID --INCREMENT FOR NEXT BUCKET ID
, (
SELECT ISNULL(MIN(ITEMID), 0)
FROM @ITEM I2
WHERE I2.SIZE <= (
SELECT SIZE
FROM @BUCKET
WHERE BUCKETID = (1)
)
) --PICK FIRST ITEM ID MATCH
+ (
CASE
WHEN (
SELECT ISNULL(MIN(ITEMID), 0)
FROM @ITEM I3
WHERE I3.SIZE <= (
SELECT SIZE
FROM @BUCKET
WHERE BUCKETID = (1)
)
) IS NOT NULL
THEN 1
ELSE 0
END
) NEXT_ITEMID --IF THE ITEM IS PLACED IN THE BUCKET THEN INCREMENTS THE FIRST ITEM ID
, (
SELECT SIZE
FROM @BUCKET
WHERE BUCKETID = (1 + 1)
) NEXT_BUCKET_SIZE --STATES THE NEXT BUCKET SIZE
FROM @BUCKET B
WHERE BUCKETID = 1
UNION ALL
--RECURSIVE PART
SELECT NEXT_BUCKETID BUCKETID
, (
SELECT ITEMID
FROM @ITEM I2
WHERE I2.SIZE <= NEXT_BUCKET_SIZE
AND I2.ITEMID = NEXT_ITEMID
) ITEMID -- PICKS THE ITEM ID IF IT IS PLACED IN THE BUCKET
, NEXT_BUCKETID + 1 NEXT_BUCKETID --INCREMENT FOR NEXT BUCKET ID
, NEXT_ITEMID + (
CASE
WHEN (
SELECT I3.ITEMID
FROM @ITEM I3
WHERE I3.SIZE <= NEXT_BUCKET_SIZE
AND I3.ITEMID = NEXT_ITEMID
) IS NOT NULL
THEN 1
ELSE 0
END
) NEXT_ITEMID --IF THE ITEM IS PLACED IN THE BUCKET THEN INCREMENTS THE CURRENT ITEM ID
, (
SELECT SIZE
FROM @BUCKET
WHERE BUCKETID = (NEXT_BUCKETID + 1)
) NEXT_BUCKET_SIZE --STATES THE NEXT BUCKET SIZE
FROM CTE
WHERE NEXT_BUCKETID <= (
SELECT CNT
FROM TOTAL_BUCKETS
) --HALTS THE RECURSION
)
SELECT
BUCKETID
, ITEMID
FROM CTE