2010-05-29 74 views
1

我有一個sql場景,我一直在嘗試改進。SQL爲用戶分配ID的場景

有一張「退貨」表,其中有退貨的ID與商品的商店相關。其結構如下。

Returns 
------------------------- 
Return ID | Shop | Item 
------------------------- 
    1   Shop1 Item1 
    2   Shop1 Item1 
    3   Shop1 Item1 
    4   Shop1 Item1 
    5   Shop1 Item1 

還有一個表供應商與商店,供應商和項目如下所示。

Supplier 
--------------------------------- 
Supplier | Shop | Item | Volume 
--------------------------------- 
    supp1 Shop1 Item1 20% 
    supp2 Shop1 Item1 80% 

現在你看到supp1的總供應量ITEM1的20%,supp2是提供項目1的80%至shop1。同一Shop1有5件商品對同一商品1返還。 現在我需要爲Supp1分配任何四個返回ID,剩下一個返回Id給supp2。這個數字的分配基於供應商供應量百分比的比例。該分配根據供應物品的數量比例而變化。

現在我已經嘗試了使用臨時表使用RANK的方法,如下所示。

臨時表1將有Shop,Return Id,Item,返回ID的總數和返回ID的等級。

臨時表2將有店鋪,供應商,項目及其比例和等級的比例。

現在我面臨着如上圖所示將頂級退貨ID分配給頂級供應商的困難。由於SQL不具有循環,我怎麼才能做到這一點。我一直在嘗試多種方法。

我的環境是Teradata(ANSI SQL就足夠了)。

回答

1

更新: 您需要循環,這裏有一些SQL代碼可以用作起點。 基本上我使用臨時標籤和ROW_NUMBER()。 在我的示例我使用SQL Server 2008的

嘗試以下操作:

-- gather suppliers in temp table 
DECLARE @SupplierTemp table 
     ( [RowId] int 
      ,[Supplier] nvarchar (50) 
      ,[ReturnCount] int) 

-- gather supplier with return count 
INSERT INTO @SupplierTemp 
    SELECT ROW_NUMBER() OVER(ORDER BY [Supplier].[Supplier] DESC, [Supplier].[Supplier]) 
     ,[Supplier].[Supplier] 
     , COUNT([Supplier].[Supplier])*[Supplier].[Volume]/100 AS ReturnCount 
    FROM [Supplier] 
    INNER JOIN [Returns] ON (([Returns].[Item] = [Supplier].[Item]) 
         AND ([Returns].[Shop] = [Supplier].[Shop])) 
    GROUP BY [Supplier].[Supplier], [Supplier].[Volume] 
    ORDER BY [Supplier].[Supplier] 

-- gather returns in temp table 
DECLARE @ReturnsTemp table 
     ( [RowId] int 
     ,[Id] int) 

-- gather returns 
INSERT INTO @ReturnsTemp 
    SELECT ROW_NUMBER() OVER(ORDER BY [Returns].[Id] DESC, [Returns].[Id]) 
     ,[Returns].[Id] 
    FROM [Returns] 

-- gather results in temp table 
DECLARE @ResultsTemp table 
     ( [Supplier] nvarchar(50) 
     ,[Id] int) 

DECLARE @rrowid as int 
DECLARE @rid as int 

-- loop over all suppliers 
-- loop once for each [ReturnCount] 
-- find the next avialable Id 
DECLARE @srowid as int 
DECLARE @loopCnt as int 
DECLARE @supplier as nvarchar(50) 

-- get first supplier 
SELECT @srowid = (SELECT MIN([RowId]) FROM @SupplierTemp) 
SELECT @loopCnt = [ReturnCount] FROM @SupplierTemp WHERE [RowId] = @srowid 
SELECT @supplier = [Supplier] FROM @SupplierTemp WHERE [RowId] = @srowid 

-- loop over suppliers 
WHILE @srowid IS NOT NULL 
    BEGIN 
    -- loop of number of returns  
    WHILE @loopCnt > 0 
     BEGIN 
     -- find the Id to return 
     SELECT @rrowid = (SELECT MIN([RowId]) FROM @ReturnsTemp) 
     SELECT @rid = [Id] FROM @ReturnsTemp WHERE [RowId] = @rrowid 

     INSERT INTO @ResultsTemp VALUES (@supplier, @rid) 

     DELETE FROM @ReturnsTemp WHERE [RowId] = @rrowid 

     SELECT @loopCnt = @loopCnt - 1 
     END 

    -- delete current item from table to keep loop moving forward...  
    DELETE FROM @SupplierTemp WHERE [RowId] = @srowid 

    -- get next supplier. 
    SELECT @srowid = (SELECT MIN([RowId]) FROM @SupplierTemp) 
    SELECT @loopCnt = [ReturnCount] FROM @SupplierTemp WHERE [RowId] = @srowid 
    SELECT @supplier = [Supplier] FROM @SupplierTemp WHERE [RowId] = @srowid 
    END 

SELECT * FROM @ResultsTemp 
+0

我錯過讀我的第一個回答你的問題。 – Zamboni 2010-05-29 17:36:05

+0

非常感謝。我會研究它並更新你。再次感謝 – 2010-05-31 08:49:53