2010-05-29 83 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