views:

377

answers:

2

Using SQL Server 2005. I am building an inventory/purchasing program and I’m at the point where I need the user to “check out” equipment. When he selects a product, I need to query which stock locations have the available Qty, and tell the user which location to walk to/ retrieve product.

Here is a query for a particular [StockLocation_Products].ProductID, with a particular assigned [ProductUsages].ProductUsageID.

SELECT 
  PROD.ProductID,
  PROD.ProductName,
  SL.Room,
  SL.StockSpace,
  SLPPU.ResvQty,
  PRDUSG.ProductUsage
FROM [StockLocations] SL 
INNER JOIN [StockLocation_Products] SLP ON SL.StockLocationID = SLP.StockLocationID 
INNER JOIN [StockLocation_Product_ProductUsages] SLPPU ON SLP.StockLocationID = SLPPU.StockLocationID AND SLP.ProductID = SLPPU.ProductID 
INNER JOIN [ProductUsages] PUSG ON SLPPU.ProductUsageID = PRDUSG.ProductUsageID 
INNER JOIN [Products] PROD ON SLPPU.ProductID = PROD.ProductID
WHERE SLP.ProductID = 4 AND PRDUSG.ProductUsageID = 1

This query returns:

ProductID ProductName           Room    StockSpace  ResvQty ProductUsage
------------------------------------------------------------------------------------------------------------------------
4   Addonics Pocket DVD+/-R/RW  B700    5-D         12      MC Pool
4   Addonics Pocket DVD+/-R/RW  B700    6-B         10      MC Pool
4   Addonics Pocket DVD+/-R/RW  B700    6-C         21      MC Pool
4   Addonics Pocket DVD+/-R/RW  B700    6-D         20      MC Pool

I thought maybe I could use an additional HAVING clause to make this query return which combination of StockSpace(s) you’d need to visit to satisfy a request for some Qty. E.g. User needs to pull 30 of Product (ID =4).

But I don’t really understand how to use GROUP BY with HAVING SUM(), to achieve what I want.

I tried various things in my group by / having clause, but I just don’t get any results.

GROUP BY PROD.ProductID,PROD.ProductName,SL.Room,SL.StockSpace,SLPPU.ResvQty,PUSG.ProductUsage
HAVING SUM(ResvQty) >= 30;

I want results that show (at least one) combination of StockSpaces which sums up to 30, so I can tell the user “you can get 21 units from space ‘6-C’, and 9 units from ‘6-B’. There may be multiple combinations of rows that could sum() >= 30, but I need at least how to find one combination that does! Help!

+1  A: 

You can have an inner select, such as:

SELECT count_of_foo, count(bar), baz
FROM (SELECT count(foo) as count_of_foo, bar, baz, other1, other2 FROM complex_query WHERE foo = bar HAVING count(foo) > 1) inner_query
GROUP BY count_of_foo, baz.

This will give you the ability to add more group by after the HAVING clause.

MatthieuF
Sorry. Maybe I'm just too new at this, but all the foo,bar,baz,etc. is not helping me.
A: 

What you are trying to do is a running sum, which you can get with various techniques in SQL. I think the most efficient query, especially if you are trying to do this all in the same query, is to use a CTE (here's one example).

Another technique that doesn't rely on CTE requires the data to be populated into another table (could be a temp table, though) and basically you do a join-and-sort operation as you go.

Once you get the data to include a running sum, then you can simply select the values from which the running sum is less than or equal to the total number that you are trying to locate.

And here is a nice summary of several of the different techniques.

Michael Bray
Well you gave me the concept to look for, and the clearest example I found was at http://dev.mysql.com/tech-resources/articles/rolling_sums_in_mysql.htm.Although he's using MySQL, that author really breaks it down more clearly than any other that you linked.>>>> "Once you .. include a running sum, then you can select the values from which the running sum is less than or equal to the total number you are trying to locate."This sentence helped me finish up after I had followed his example. Thanks.
Sorry, that link is missing the trailing 'L'. It is supposed to be:http://dev.mysql.com/tech-resources/articles/rolling_sums_in_mysql.html