Solved

Anyway to do this in TSQL (2005) without a cursor?

Posted on 2008-10-07
9
211 Views
Last Modified: 2010-03-19
using SQL Server 2005;

I have two tables: Demand and Supply.  I need to determine for each record in the demand table which record in supply table it can consume.

These are the demand and supply table and sample data.

CREATE TABLE Demand
( Priority INT,
Food VARCHAR(10),
      Qty INT)
      
INSERT INTO Demand
      Select 1, 'Apples', 2
      UNION ALL
      Select 2, 'Apples', 5
      UNION ALL
      Select 3, 'Apples', 4
      UNION ALL
      Select 4, 'Apples', 10
      UNION ALL
      Select 5, 'Apples', 15


CREATE TABLE Supply
( SourceID INT,
Food VARCHAR(10),
      Qty INT)
      
INSERT INTO Supply
      Select 1, 'Apples', 10
      UNION ALL
      Select 2, 'Apples', 20
      UNION ALL
      Select 3, 'Apples', 5


----------------------------------
The end result I'm trying to obtain is like so:
Priority      Food      Qty            SupplyID
1      Apples      2            1
2      Apples      5            1
3      Apples      4            2
4      Apples      10            2
5      Apples      15            NULL

Thanks,
sopheak
0
Comment
Question by:sopheak
  • 6
  • 3
9 Comments
 

Author Comment

by:sopheak
Comment Utility
I guess it would be okay to use a cursor in answer too, it may be faster depending on the amount of data.
0
 
LVL 59

Expert Comment

by:Kevin Cross
Comment Utility
I don't have my SQL Management Studio, but this should parse out fine.
-- create a view for demand

CREATE VIEW dbo.vw_DemandTotalsByFoodAndPriority AS

;WITH demandCTE AS (

    SELECT *, row_number() OVER (PARTITION BY Food ORDER BY Priority) As dRow

    FROM Demand

)

SELECT d1.Food, d1.Priority, d1.Qty, d1.Qty + IsNull(d2.Qty, 0) AS TotalDemand

FROM demandCTE d1 LEFT JOIN demandCTE d2

ON d1.Food = d2.Food AND d1.dRow - 1 = d2.dRow;

GO
 

-- create a view for supply

CREATE VIEW vw_SupplyTotalsByFoodAndSourceID AS

;WITH supplyCTE AS (

    SELECT *, row_number() OVER (PARTITION BY Food ORDER BY SourceID) As sRow

    FROM Supply

)

SELECT s1.Food, s1.SourceID, s1.Qty, s1.Qty + IsNull(s2.Qty, 0) AS TotalSupply

FROM supplyCTE s1 LEFT JOIN supplyCTE s2

ON s1.Food = s2.Food AND s1.sRow - 1 = s2.sRow;

GO
 

SELECT d.Priority, d.Food, d1.Qty, s.SourceID

FROM vw_DemandTotalsByFoodAndPriority d LEFT JOIN vw_SupplyTotalsByFoodAndSourceID s

ON d.Food = s.Food AND d.TotalDemand <= s.TotalSupply

ORDER BY 2, 1

Open in new window

0
 
LVL 59

Expert Comment

by:Kevin Cross
Comment Utility
Sorry,filled with type-o's -- use THIS:
-- create a view for demand

CREATE VIEW dbo.vw_DemandTotalsByFoodAndPriority AS

WITH demandCTE AS (

    SELECT *, row_number() OVER (PARTITION BY Food ORDER BY Priority) As dRow

    FROM Demand

)

SELECT d1.Food, d1.Priority, d1.Qty, d1.Qty + IsNull(d2.Qty, 0) AS TotalDemand

FROM demandCTE d1 LEFT JOIN demandCTE d2

ON d1.Food = d2.Food AND d1.dRow - 1 = d2.dRow;

 

-- create a view for supply

CREATE VIEW vw_SupplyTotalsByFoodAndSourceID AS

WITH supplyCTE AS (

    SELECT *, row_number() OVER (PARTITION BY Food ORDER BY SourceID) As sRow

    FROM Supply

)

SELECT s1.Food, s1.SourceID, s1.Qty, s1.Qty + IsNull(s2.Qty, 0) AS TotalSupply

FROM supplyCTE s1 LEFT JOIN supplyCTE s2

ON s1.Food = s2.Food AND s1.sRow - 1 = s2.sRow;

 

SELECT        Priority, Food, Qty,

                             (SELECT        MIN(SourceID) AS Expr1

                               FROM            vw_SupplyTotalsByFoodAndSourceID AS s

                               WHERE        (d.Food = Food) AND (d.TotalDemand <= TotalSupply)) AS SupplyID

FROM            vw_DemandTotalsByFoodAndPriority AS d

ORDER BY Food, Priority

Open in new window

0
 

Author Comment

by:sopheak
Comment Utility
unfortunately the results don't come out correct;  this is the result from your solution.  For Example, record 3 cannot pull from supplyID 1 because record 1 and 2 already consumed a total of 9 ,so only one is left.  Record 3 should pull the remainder from supplyid 2.

I guess I need to clarify that I want the last supply line a record would pull from to satify the demand.

tahnks

Priority      Food      Qty      SupplyID
1      Apples      2      1
2      Apples      5      1
3      Apples      4      1
4      Apples      10      2
5      Apples      15      2

0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 59

Accepted Solution

by:
Kevin Cross earned 250 total points
Comment Utility
Check the views independently and make sure the total demands look correct.  Should go 2, 7, 11, and so on.  I will check when I get home as I have this data loaded there and I got results you requested when I tested last night.
0
 
LVL 59

Expert Comment

by:Kevin Cross
Comment Utility
Sorry I posted the wrong code version... I will post in a few minutes.
0
 

Author Comment

by:sopheak
Comment Utility
I modified your Demand view and it works now:

CREATE VIEW dbo.vw_DemandTotalsByFoodAndPriority AS
WITH demandCTE AS (
    SELECT *, row_number() OVER (PARTITION BY Food ORDER BY Priority) As dRow
    FROM Demand
)
SELECT  d1.Food,
        d1.Priority,
        d1.Qty,
        (SELECT SUM(Qty)
            FROM demandCTE
            WHERE d1.Food = Food AND d1.dRow >= dRow) AS 'TotalDemand'
FROM    demandCTE d1
0
 
LVL 59

Expert Comment

by:Kevin Cross
Comment Utility
This is what I meant to post, sorry!
DROP VIEW vw_SupplyTotalsByFoodAndSourceID

GO

DROP VIEW vw_DemandTotalsByFoodAndPriority

GO
 

-- create a view for demand

CREATE VIEW dbo.vw_DemandTotalsByFoodAndPriority AS

SELECT d1.Food, d1.Priority, d1.Qty

, d1.Qty + IsNull((SELECT SUM(QTY) FROM demand d2 WHERE d2.Food = d1.Food AND d2.Priority < d1.Priority ), 0) AS TotalDemand

FROM demand d1;

 GO

-- create a view for supply

CREATE VIEW vw_SupplyTotalsByFoodAndSourceID AS

SELECT s1.Food, s1.SourceID, s1.Qty

, s1.Qty + IsNull((SELECT SUM(QTY) FROM supply s2 WHERE s1.Food = s2.Food AND s2.SourceID < s1.SourceID ), 0) AS TotalSupply

FROM supply s1

 GO
 

SELECT        Priority, Food, Qty,

                             (SELECT        MIN(SourceID) AS Expr1

                               FROM            vw_SupplyTotalsByFoodAndSourceID AS s

                               WHERE        (d.Food = Food) AND (d.TotalDemand <= TotalSupply)) AS SupplyID

FROM            vw_DemandTotalsByFoodAndPriority AS d

ORDER BY Food, Priority

Open in new window

0
 
LVL 59

Expert Comment

by:Kevin Cross
Comment Utility
Glad you figured it out as well.  I apologize as I saw that needed to include all the rows previous to current one instead of the last one.  
0

Featured Post

Backup Your Microsoft Windows Server®

Backup all your Microsoft Windows Server – on-premises, in remote locations, in private and hybrid clouds. Your entire Windows Server will be backed up in one easy step with patented, block-level disk imaging. We achieve RTOs (recovery time objectives) as low as 15 seconds.

Join & Write a Comment

by Mark Wills PIVOT is a great facility and solves many an EAV (Entity - Attribute - Value) type transformation where we need the information held as data within a column to become columns in their own right. Now, in some cases that is relatively…
Introduction: When running hybrid database environments, you often need to query some data from a remote db of any type, while being connected to your MS SQL Server database. Problems start when you try to combine that with some "user input" pass…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now