|
I would question the use of an approximate data type (FLOAT) for the transaction quantities instead of an exact type such as NUMERIC(15,8). If you're not dealing with fractions of items you might even get away with INT.
I would also ask why PartDesc is in this table. Do the descriptions vary over time? If you use "GROUP BY PartNo, PartDesc" you'll get multiple rows for the same part number, which I assume is not desirable. Database normalization rules would suggest a separate table with (PartNo, PartDesc).
But back to your query, I'm assuming the Opening Stock is StkInHand from the earliest transaction for a PartNo, and PartDesc is taken from the most recent. The first version does it with one subquery.
SELECT PartNo, PartDesc = MAX(CASE WHEN Latest = 1 THEN PartDesc END), OpStk = MAX(CASE WHEN Earliest = 1 THEN StkInHand END), NewPur = SUM(NPurQ), QtyIss = SUM(IssQty), BalStk = MAX(CASE WHEN Earliest = 1 THEN StkInHand END) + SUM(NPurQ) + SUM(IssQty) FROM ( SELECT PartNo, PartDesc, StkInHand, NPurQ, IssQty, Earliest = ROW_NUMBER() OVER (PARTITION BY PartNo ORDER BY RepDate), Latest = ROW_NUMBER() OVER (PARTITION BY PartNo ORDER BY RepDate DESC) FROM dbo.StoTrans ) st GROUP BY PartNo
The second version uses separate subqueries and is IMHO more readable and maintainable. It may perform differently than the first if the table gets very large, but you'd have to have a large table for testing to prove it.
SELECT trans.PartNo, pt.PartDesc, OpStk = InitialStock, NewPur, QtyIss, BalStk = InitialStock + NewPur + QtyIss FROM ( -- Get aggregate values from all transactions SELECT PartNo, NewPur = SUM(NPurQ), QtyIss = SUM(IssQty) FROM dbo.StoTrans GROUP BY PartNo ) trans INNER JOIN ( -- Find earliest StkInHand SELECT PartNo, InitialStock = StkInHand, Sequence = ROW_NUMBER() OVER (PARTITION BY PartNo ORDER BY RepDate) FROM dbo.StoTrans ) init ON trans.PartNo = init.PartNo AND init.Sequence = 1 INNER JOIN ( -- Find most recent PartDesc SELECT PartNo, PartDesc, Sequence = ROW_NUMBER() OVER (PARTITION BY PartNo ORDER BY RepDate DESC) FROM dbo.StoTrans ) pt ON trans.PartNo = pt.PartNo AND pt.Sequence = 1
|