SQL Сценарий распределения идентификаторов пользователю - PullRequest
1 голос
/ 29 мая 2010

У меня есть сценарий sql, который я пытаюсь улучшить.

Существует таблица «Возвраты», в которой указаны идентификаторы возвращенных товаров в магазине для предмета. Его структура, как показано ниже.

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 поставляет 20% от общего объема item1, а supp2 поставляет 80% Item1 в магазин1. И было 5 возвратов предметов против того же Item1 для того же Shop1. Теперь мне нужно выделить любые четыре идентификатора возврата для Supp1 и оставшийся один идентификатор возврата для Supp2. Это распределение чисел основано на соотношении поставляемого объема в процентах от поставщика. Это распределение варьируется в зависимости от соотношения объема поставляемых предметов.

Теперь я попробовал метод использования рангов, как показано ниже, с использованием временных таблиц.

временная таблица 1 будет иметь магазин, идентификатор возврата, предмет, общее количество идентификаторов возврата и ранг идентификатора возврата.

временная таблица 2 будет иметь магазин, Поставщика, Предмет и его пропорцию и ранг пропорции.

Теперь я сталкиваюсь с трудностью при распределении идентификаторов с наибольшим возвратом среди поставщиков, как показано выше. Как SQL не имеет циклов, как я могу добиться этого. Я связывал несколько способов сделать это.

Моя среда - Teradata (достаточно ANSI SQL).

1 Ответ

1 голос
/ 29 мая 2010

UPDATE: Вам нужно выполнить цикл, вот код 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
...