I have the following query which checks goods receipts against purchase orders to see what items were originally ordered and how many have been booked in via goods receipts. E.g I place a purchase order for 10 banana milkshakes, I then generate a goods receipt stating that I received 5 of these milkshakes on said purchase order.
SELECT t.PONUM, t.ITMNUM, t.ordered,
SUM(t.received) as received,
t.ordered - ISNULL(SUM(t.received),0) as remaining,
SUM(t.orderedcartons) as orderedcartons,
SUM(t.cartonsreceived) as cartonsreceived,
SUM(t.remainingcartons) as remainingcartonsFROM(SELECT pod.PONUM,
pod.ITMNUM, pod.QTY as ordered, ISNULL(grd.QTYRECEIVED, 0) as received,
pod.DELIVERYSIZE as orderedcartons,
ISNULL(grd.DELIVERYSIZERECEIVED, 0) as cartonsreceived,
(pod.DELIVERYSIZE - ISNULL(grd.DELIVERYSIZERECEIVED, 0)) as remainingcartons
FROM TBLPODETAILS pod
LEFT OUTER JOIN TBLGRDETAILS grd
ON pod.PONUM = grd.PONUM and pod.ITMNUM = grd.ITMNUM) t
GROUP BY t.ITMNUM, t.PONUM, t.ordered
ORDER BY t.PONUM
Which returns the following data:
PONUM ITMNUM ordered received remaining orderedcartons cartonsreceived remainingcartons
1 1 5.0000 3.0000 2.0000 5.0000 3.0000 2.0000
Next I have a C# loop to generate update queries based on the data I get back from the above query:
foreach (DataRow POUpdate in dt.Rows) {...
query += "UPDATE MYTABLE SET REMAININGITEMS=" + remainingQty.ToString()
+ ", REMAININGDELIVERYSIZE=" + remainingBoxes.ToString() + " WHERE ITMNUM="
+ itemNumber + " AND PONUM=" + poNumber + ";";
I then execute each update query against the DB. Which works fine on my local dev machine.
However deploying to production server pulls back over 150,000 records on that first query.
So looping around so many rows locks up SQL and my app. Is it the foreach? Is it the original select loading all that data into memory? Both? Can I make this query into one single query and cut out the C# loop? If so what's the most efficient way to achieve this?