How to solve something like "circular JOIN" on table to solve this example of a production order backtracking problem?
The problem is:
I need to store evidence of production orders.
During the production is usual that sometimes is need to split the order and continue in the production with the new order (with the relation on previous order).
See this example:
CREATE TABLE EventOrders
(
OrderID INT IDENTITY(1,1) PRIMARY KEY,
Code NVARCHAR(20),
OrderTypeID INT
);
CREATE TABLE EventSetOrderRelations
(
OrderRelationID INT IDENTITY(1,1) PRIMARY KEY,
OrderIDIn INT FOREIGN KEY REFERENCES EventOrders(OrderID),
OrderIDOut INT FOREIGN KEY REFERENCES EventOrders(OrderID)
);
INSERT INTO EventOrders (Code, OrderTypeID) VALUES
('221209-1',1),('221209-2',1),('221209-3-R',2),
('221209-4',1),('221209-5-R',2),('221209-6-R',2);
INSERT INTO EventSetOrderRelations (OrderIDIn, OrderIDOut) VALUES
(1,3),(2,5),(3,6);
SELECT * FROM EventOrders;
SELECT * FROM EventSetOrderRelations
OrderID
Code
OrderTypeID
1
221209-1
1
2
221209-2
1
3
221209-3-R
2
4
221209-4
1
5
221209-5-R
2
6
221209-6-R
2
OrderRelationID
OrderIDIn
OrderIDOut
1
1
3
2
2
5
3
3
6
Question:
I would like use some elegant query with parameter of the order (let's say that in the condition will be "Code" of the order) and get all previous orders in this branch...
My solution:
... I can solve this issue with this SQL script and the result is exactly what I need BUT I need to apply this solution in Stored Procedure...
DECLARE #MyCode NVARCHAR(20) = '221209-6-R'
DECLARE #CheckID INT
DECLARE #AllOrders TABLE (OrderID INT, Code NVARCHAR(20), OrderTypeID INT)
DECLARE #Count INT = 0
SET #CheckID = (SELECT OrderID FROM dbo.EventOrders WHERE Code = #MyCode)
-- --------------------------------------------------
WHILE #Count < 100
BEGIN
SET #Count = #Count + 1
INSERT INTO #AllOrders (OrderID, Code, OrderTypeID)
SELECT OrderID, Code, OrderTypeID FROM dbo.EventOrders
WHERE OrderID = #CheckID
SET #CheckID = (SELECT OrderIDIn FROM dbo.EventSetOrderRelations ESOR
JOIN dbo.EventOrders EO ON EO.OrderID = ESOR.OrderIDOut
WHERE EO.OrderID = (SELECT MIN(OrderID) FROM #AllOrders))
IF #CheckID IS NULL
BEGIN
SET #Count = 100
END
END
SELECT * FROM #AllOrders ORDER BY OrderID ASC
OrderID
Code
OrderTypeID
1
221209-1
1
3
221209-3-R
2
6
221209-6-R
2
My wonder:
I would like to ask You if is possible some easier way to get this result.
See DBFiddle:
fiddle link
Seems that what you want is a recursive Common Table Expression (rCTE) here. You can pass the parameter for the order in the first query within the rCTE, and then use that data to recurse through the table(s):
WITH rCTE AS(
SELECT EO.*
FROM dbo.EventOrders EO
WHERE EO.OrderID = #Order
UNION ALL
SELECT EO.*
FROM dbo.EventOrders EO
JOIN EventSetOrderRelations ESOR ON EO.OrderID = ESOR.OrderIDIn
JOIN rCTE r ON ESOR.OrderIDOut = r.OrderID)
SELECT *
FROM rCTE;
Related
Was wondering if you can correct my syntax.
update TestTable
set test_person = CAST(test_person as Varchar = 'TEST' (50)) + 1
Im trying to update all columns in a table and increment it by 1 (hence the cast since the column is a string).
T-SQL
DECLARE #counter INT = 0
UPDATE TestTable
SET test_person = 'Test' + CAST(#counter AS VARCHAR(16)), #counter = #counter + 1
Something I've done in the past to do incrementing values in a string column is something like this:
http://sqlfiddle.com/#!6/7f0f5/2
create table testTable (id int primary key identity(1,1), test_person varchar(100))
insert into testTable (test_person)
select 'bob loblaw'
union all select 'Buster Bluth'
union all select 'Jason Bateman'
union all select 'gob'
union all select 'Lucille #2'
update testTable
set test_person = 'test ' + convert(varchar(30), id)
select * from testTable
results:
ID TEST_PERSON
1 test 1
2 test 2
3 test 3
4 test 4
5 test 5
note this works when your table has an identity primary key. You did not give your entire table schema, but if it does not have this identity primary key you could do something similar by creating a temp/variable table to hold your data that does have an int primary key to do the same thing.
Another option would be to use a loop/cursor to do your population... but that's kind of a pain to write.
Another option would be to use ROW_NUMBER which is sql server (not sure about others). Without the full table schema i can only give an example of how to accomplish:
seen in fiddle: http://sqlfiddle.com/#!6/7f0f5/5
update testTable
set test_person = 'test ' + convert(varchar(30), rowNum)
from testTable
inner join (
-- create an incrementing number for each row
select row_number() over(order by test_person) as rowNum, test_person
from testTable
) rows on testTable.test_person = rows.test_person
select * from testTable
I have five tables named guest, orders, order_details, food, and employees. Their characteristics are as follows:
create table guest
(
guest_id int primary key identity(1,1),
guest_fname nvarchar(50),
national_id int,
mobile nvarchar(50),
nationality_id int
constraint c15
foreign key(nationality_id) references nationality(nationality_id)
)
create table employees
(
emp_id int primary key ,
emp_fname nvarchar(50),
constraint c1
--foreign key(mgr_id) references employees(emp_id),
foreign key(super_id) references employees(emp_id),
)
go
create table food
(
food_id int primary key identity(1,1),
food_name nvarchar(50),
food_price money,
food_desc nvarchar(200),
cat_id int
constraint c5
foreign key(cat_id) references food_categories(cat_id)
)
go
create table orders
(
order_id int primary key identity(1,1),
order_date datetime,
total float,
guest_id int,
emp_id int,
is_paid bit
constraint c6
foreign key(guest_id) references guest(guest_id),
foreign key(emp_id) references employees(emp_id)
)
go
create table order_details
(
order_id int,
food_id int,
price money,
qty int
constraint c7
primary key(order_id,food_id),
foreign key(order_id) references orders(order_id),
foreign key(food_id) references food(food_id)
)
Go
There is a 1-to-M relationship between orders and order_details.
I want to insert a single row into orders and multiple rows into order_details via a stored procedure. Please help me!
Please give me a stored procedure and explain its algorithm to point me in the right direction.
As #thepirat000 points out, you can use a TVP for the order details/line items since you are using SQL Server 2012. Pinal Dave has a great article on TVPs that you may find helpful. Combine the TVP with scalar parameters for order properties.
For example:
-- NOTE: *Not* accounting for order_id in this case - i.e. a new order where
-- order_id is an identity value.
CREATE TYPE [dbo].[order_details_type] AS TABLE
(
food_id int,
price money,
qty int
)
GO
CREATE PROCEDURE [dbo].[usp_insert_order]
(
#order_id int output,
#order_date datetime = NULL,
#total float,
#guest_id int,
#emp_id int,
#is_paid bit = 0,
#details order_details_type readonly
)
AS
BEGIN
SET NOCOUNT ON;
-- TODO: Wrap the inserts into dbo.orders and dbo.order_details in a
-- transaction as desired.
-- TODO: Check that #order_id does not already exist in dbo.orders and
-- dbo.order_details etc.
-- FORNOW: Proceed optimistically. :}
IF #order_date IS NULL
SET #order_date = GETDATE();
INSERT INTO dbo.orders (order_date, total, guest_id, emp_id, is_paid)
VALUES (#order_date, #total, #guest_id, #emp_id, #is_paid);
SET #order_id = SCOPE_IDENTITY();
INSERT INTO dbo.order_details (order_id, food_id, price, qty)
SELECT #order_id, food_id, price, qty
FROM #details;
END
GO
Executing such a stored procedure is pretty straighforward, as you prepare the TVP argument much like you would a table variable:
/*
* Order up!
*/
/* data I added for a quick check
SELECT TOP 1 * FROM dbo.employees;
--emp_id emp_fname
--1 Wendy
SELECT TOP 1 * FROM dbo.guest;
--guest_id guest_fname national_id mobile
--1 Joe 1 619-555-1212
SELECT TOP 2 * FROM dbo.food;
--food_id food_name food_price food_desc
--1 Onion Rings 5.00 Beer-battered onion rings.
--2 Kobe Burger 10.00 Kobe-beef burger.
*/
-- Prepare the order.
DECLARE #order_id int; -- to get on order insert
DECLARE #now datetime = getdate();
DECLARE #order_details order_details_type;
INSERT INTO #order_details
SELECT 1, 5, 1
UNION
SELECT 2, 10, 2;
-- Insert the order.
EXEC dbo.usp_insert_order
#order_id = #order_id OUTPUT,
#order_date=#now,
#total=25,
#guest_id=1,
#emp_id=1,
#is_paid=0,
#details=#order_details;
/*
* Check the order.
*/
SELECT * FROM dbo.orders WHERE order_id = #order_id;
--order_id order_date total guest_id emp_id is_paid
--1 2014-03-13 21:44:45.400 25 1 1 0
SELECT * FROM dbo.order_details WHERE order_id = #order_id;
--order_id food_id price qty
--1 1 5.00 1
--1 2 10.00 2
Another option that pre-dates TVPs may interest you too - using an XML parameter for the order details/line items and scalar parameters for order properties. Related resources and examples abound.
A variation of the XML-param approach that is to pass XML for the order and its details/line items; but I think this is overkill personally.
you need 2 store procs, 1 for order and 1 for Order_details, in the last one add update statement for food table qty. you do not want to make 1 sproc for all
Here is my sample table, the primary key is a composite key of Akey+Bkey
Akey Bkey ItemSequence
---- ---- ------------
1 1 1
1 5 2
1 7 3
2 7 1
3 2 1
3 3 2
Akey is generated from a SQL 2012 Sequence object ASequence. In most cases I insert one row at a time and when necessary I call NEXT VALUE FOR ASequence. However I need to do an insert from a statement like:
SELECT DENSE_RANK() OVER ( ORDER BY Something) as AKey,
Bkey, Sequence
FROM TABLEB
The OVER clause of the NEXT VALUE does not work this way as I need to be able to insert records as a SET but only increment the Sequence once per DENSE_RANK set.
So we have the ALTER SEQUENCE command and with this I am able to set the sequence to what I want. The caveat to this is that it must be a constant and will not accept a variable. My workaround to this was:
DECLARE #startingID INT
DECLARE #sql VARCHAR(MAX)
DECLARE #newSeed INT
SET #startingID = NEXT VALUE FOR ASequence
INSERT TABLEA
SELECT DENSE_RANK() OVER ( ORDER BY Something) + #startingID as AKey,
Bkey, Sequence
FROM TABLEB
SELECT #newSeed = MAX(Akey) FROM TABLEA
SET #sql = ‘ALTER SEQUENCE ASEQUENCE RESTART WITH ‘ + cast(#newSeed+1 as varchar(10))
EXEC(#sql)
Seems terrible to have DML statements in Dynamic SQL like this. Is there a better way to do this?
This should do it:
INSERT TABLEA
SELECT NEXT VALUE FOR ASequence OVER(ORDER BY Something) as AKey,
Bkey, Seq
FROM TABLEB
Or, how about this:
CREATE TABLEA
(
GroupID INT,
AKey INT,
BKey INT,
ItemSequence INT,
CONSTRAINT PK_TABLEA PRIMARY KEY CLUSTERED
(
GroupID,
AKey,
BKey
)
)
DECLARE #GroupID INT
SET #GroupID = NEXT VALUE FOR ASequence
INSERT TABLEA
SELECT #GroupID, DENSE_RANK() OVER ( ORDER BY Something) as AKey,
Bkey, Sequence
FROM TABLEB
and if you need the value of AKey as it is in your example, you can do GroupID+AKey here.
Loooking for a way to retrieve community from a large dataset I came across an article about the algorithm which seems to be apropriate for large datasets. Anyway the data is stored two tables: users (nodes) and connections and I would like to retrieve the communities by pure sql queries without help of custom applications (I'm using SQL Server 2008).
The algorithm to retrieve the cliques is the following:
Read the graph G
Generate set neighbors(v) for every vertex of G
for each vertex v of G
call recursive_find_cliques(v, neighbors(v))
end for
Function recursive_find_cliques(x, n)
for each vertex t ∈ n by ascending order calculate set sigma
if sigma is not empty
extend x with t
call recursive_find_cliques(x, sigma)
end if
end for
where sigma is the set of vertices that could constitute triangles with v and its neighbors.
I already created a stored procedure which returns a table of neighbors of selected node but so far I haven't delat with sql functions and advanced queries so the question is the following:
Does anyone know how to rewrite the
algorithm above in sql in order to get
the set of cliques? As the question
might be a little abstract, I may
point out that the main problem is to
create a recursive function
(recursive_find_cliques(x, n)) which
takes a table (n) as an argument).
Thank you!
EDIT:
Here is sthe stored procedure created so far:
CREATE PROCEDURE [dbo].[Peamc_Test]
AS
BEGIN
SET XACT_ABORT ON
BEGIN TRAN
SET NOCOUNT ON;
CREATE TABLE #Users
(
UserId int NOT NULL,
userLabel varchar(50) PRIMARY KEY NOT NULL,
Observed bit NOT NULL
)
CREATE TABLE #Neighbors
(
UserId int NOT NULL,
userLabel varchar(50) NOT NULL PRIMARY KEY,
Retrieved bit NOT NULL
)
CREATE TABLE #ConnectedVertices
(
UserId int NOT NULL,
userLabel varchar(50) NOT NULL PRIMARY KEY,
)
CREATE TABLE #Cliques
(
CliqueId int NOT NULL,
UserId varchar(50) NOT NULL,
)
DECLARE #UsersCount int
DECLARE #ii int
DECLARE #User varchar(50)
DECLARE #NeighborsCount int
INSERT INTO #Users(UserId, userLabel, Observed) SELECT user_id, userLabel, 0 FROM dbo.test_users WHERE user_id IS NOT NULL
SELECT #UsersCount = COUNT(*) FROM #Users
SELECT #ii = 1
WHILE #ii <= #UsersCount
BEGIN
--select user
SELECT TOP 1 #User = userLabel FROM #Users WHERE Observed = 0 ORDER BY UserId
UPDATE #Users SET Observed = 1 WHERE userLabel = #User
--Get user's neighbors
DELETE FROM #Neighbors
INSERT INTO #Neighbors(UserId, userLabel, Retrieved)
SELECT u.user_id, t2.neighbor, 0 FROM ( SELECT CALLING_NEIGHBORS.neighbor FROM ( SELECT mc.calling_party AS neighbor FROM monthly_connections_test mc WHERE mc.called_party = #User) AS CALLING_NEIGHBORS INNER JOIN (SELECT mc.called_party AS neighbor FROM monthly_connections_test mc WHERE mc.calling_party = #User) AS CALLED_NEIGHBORS ON CALLING_NEIGHBORS.neighbor = CALLED_NEIGHBORS.neighbor) AS t2 INNER JOIN test_users u ON t2.neighbor = u.userLabel
SELECT #NeighborsCount = COUNT(*) FROM #Neighbors
SELECT #ii = #ii + 1
--HERE the function recursive_find_cliques has to search for cliques and insert the found ones in #cliques
END
SELECT * FROM #Cliques
END
It does'not return anything yet as it is not finished. It though retrieves all neighbors for the currently selected nodes and the next step is to implement recursive_find_cliques function.
I realised that my first answer only works when each clique has at least one user who is not referred to by any others in that clique. In other words, closed cliques like A-B, B-C, C-A will not be found.
Here is a solution which solves this. Again we have users with IDs, now 1..20. There are several cases of neighbouring relations that need to be handled:
Compared to the simple case, it is harder to find a unique starter for each clique.
We achieve this with a little sleight of hand:
Reorder the neighbours so that for all references A-B, A is less than B, ignoring any A=B.
From these, remove any A-X references if there are any X-A, which could cause a loop. This will never remove references to A completely because X-A remains and A-X will be added in the recursion.
The resultant set are the 'starting' users and we use them to prime the CTE:
-- Get all pairs, where UserA < UserB, dropping any A=B or B=A
WITH LRNeighbours(A, B) AS (
SELECT
Neighbours.UserA, Neighbours.UserB
FROM
Neighbours
WHERE
Neighbours.UserA < Neighbours.UserB
UNION ALL
SELECT DISTINCT
Neighbours.UserB, Neighbours.UserA
FROM
Neighbours
WHERE
Neighbours.UserA > Neighbours.UserB
),
-- Isolate those that are not referred to by a higher numbered key
Starters(userid) AS (
SELECT DISTINCT
A
FROM
LRNeighbours
WHERE
A NOT IN (
SELECT
B
FROM
LRNeighbours
)
),
-- The recursive Common Table Expression
cliques(userid, clique) AS (
-- Number starters 1..N
SELECT
userid, ROW_NUMBER() OVER(ORDER BY userid) AS clique
FROM
Starters
UNION ALL
-- Recurse, adding users referred by siblings, avoiding starters themselves
SELECT
B, clique
FROM
LRNeighbours INNER JOIN
cliques ON
LRNeighbours.A = cliques.userid
AND B NOT IN (
SELECT
userid
FROM
starters
)
)
SELECT DISTINCT
clique, userid
FROM
cliques
ORDER BY
clique, userid
Results:
1 1
1 2
2 3
2 4
3 5
3 6
3 7
3 8
4 9
4 10
4 11
4 12
4 13
5 14
5 15
5 16
5 17
5 18
5 19
5 20
CREATE TABLE [dbo].[Users](
[UserID] [int] IDENTITY(1,1) NOT NULL,
[UserName] [varchar](50) NOT NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[Neighbours](
[UserA] [int] NOT NULL,
[UserB] [int] NOT NULL
) ON [PRIMARY]
Users populated with 1..8 and Neighbours
UserA UserB
1 2
2 3
4 5
4 6
5 7
7 8
Then:
WITH cliques(userid, clique) AS (
SELECT
userid, ROW_NUMBER() OVER(ORDER BY userid) AS clique
FROM
Users
WHERE
users.UserID NOT IN (
SELECT
UserB
FROM
Neighbours
)
UNION ALL
SELECT
Neighbours.UserB, clique
FROM
neighbours
INNER JOIN cliques
ON Neighbours.UserA = cliques.userid
)
SELECT
clique, cliques.userid
FROM
cliques
ORDER BY
clique, userid
Result:
clique userid
1 1
1 2
1 3
2 4
2 5
2 6
2 7
2 8
See : Recursive Queries Using Common Table Expressions
I've added a two LABELS and two GOTO statements
CREATE PROCEDURE [dbo].[Peamc_Test]
AS
BEGIN
SET XACT_ABORT ON
BEGIN TRAN
SET NOCOUNT ON;
CREATE TABLE #Users
(
UserId int NOT NULL,
userLabel varchar(50) PRIMARY KEY NOT NULL,
Observed bit NOT NULL
)
CREATE TABLE #Neighbors
(
UserId int NOT NULL,
userLabel varchar(50) NOT NULL PRIMARY KEY,
Retrieved bit NOT NULL
)
CREATE TABLE #ConnectedVertices
(
UserId int NOT NULL,
userLabel varchar(50) NOT NULL PRIMARY KEY,
)
CREATE TABLE #Cliques
(
CliqueId int NOT NULL,
UserId varchar(50) NOT NULL,
)
DECLARE #UsersCount int
DECLARE #ii int
DECLARE #User varchar(50)
DECLARE #NeighborsCount int
INSERT INTO #Users(UserId, userLabel, Observed) SELECT user_id, userLabel, 0 FROM dbo.test_users WHERE user_id IS NOT NULL
SELECT #UsersCount = COUNT(*) FROM #Users
SELECT #ii = 1
WHILE #ii <= #UsersCount
BEGIN
--select user
SELECT TOP 1 #User = userLabel FROM #Users WHERE Observed = 0 ORDER BY UserId
UPDATE #Users SET Observed = 1 WHERE userLabel = #User
--Get user's neighbors
DELETE FROM #Neighbors
INSERT INTO #Neighbors(UserId, userLabel, Retrieved)
SELECT u.user_id, t2.neighbor, 0 FROM ( SELECT CALLING_NEIGHBORS.neighbor FROM ( SELECT mc.calling_party AS neighbor FROM monthly_connections_test mc WHERE mc.called_party = #User) AS CALLING_NEIGHBORS INNER JOIN (SELECT mc.called_party AS neighbor FROM monthly_connections_test mc WHERE mc.calling_party = #User) AS CALLED_NEIGHBORS ON CALLING_NEIGHBORS.neighbor = CALLED_NEIGHBORS.neighbor) AS t2 INNER JOIN test_users u ON t2.neighbor = u.userLabel
SELECT #NeighborsCount = COUNT(*) FROM #Neighbors
SELECT #ii = #ii + 1
GOTO Clique_Find
--HERE the function recursive_find_cliques has to search for cliques and insert the found ones in #cliques
--------------------
Clique_Return:
--------------------
END
SELECT * FROM #Cliques
END
--------------------
Clique_Find:
--------------------
-- Code goes here
-- Code goes here
-- Code goes here
-- Code goes here
-- Code goes here
-- Code goes here
GOTO Clique_Return
I have an sql scenario as follows which I have been trying to improve.
There is a table 'Returns' which is having ids of the returned goods against a shop for an item. Its structure is as below.
Returns
-------------------------
Return ID | Shop | Item
-------------------------
1 Shop1 Item1
2 Shop1 Item1
3 Shop1 Item1
4 Shop1 Item1
5 Shop1 Item1
There is one more table Supplier with Shop, supplier and Item as shown below.
Supplier
---------------------------------
Supplier | Shop | Item | Volume
---------------------------------
supp1 Shop1 Item1 20%
supp2 Shop1 Item1 80%
Now as you see supp1 is supplying 20 % of total item1 volume and supp2 is supplying 80% of Item1 to shop1. And there were 5 return of items against the same Item1 for same Shop1.
Now I need to allocate any four return IDs to Supp1 and remaining one return Id to supp2. This allocation of numbers is based on the ratio of the supplied volume percentage of the supplier. This allocation varies depending on the ratio of volume of supplied items.
Now I have tried a method of using RANKs as shown below by use of temp tables.
temp table 1 will have Shop, Return Id, Item, Total count of return IDs and Rank of the return id.
temp table 2 will have shop, Supplier, Item and his proportion and rank of proportion.
Now I am facing the difficulty in allocating top return ids to top supplier as illustrated above. As SQL doesnt have loops how can I achieve this. I have been tying several ways of doing this.
My environment is Teradata (ANSI SQL is enough).
UPDATE:
You need to loop, here is some SQL code you can use as a starting point.
Basically I use temporary tabes and ROW_NUMBER().
For my sample I used SQL SERVER 2008.
Try the following:
-- 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