Reputation: 31
I'm working on this report which is meant to return the last purchase date and last purchase quantity for a list of items.
my basic sql is as follows:
select im.ItemName, max(prh.Receiptdate), prl.ReceiptQuantity/*which corresponds with max ReceiptDate*/
from ItemMaster im
left join PurchaseReceiptLines prl on prl.ItemName = im.ItemName
left join PurchaseReceiptHeader prh on prh.ReceiptNum = prl.ReceiptNum
group by im.ItemName
Does anyone have any pointers?
Any help would be awesome
Upvotes: 1
Views: 1906
Reputation: 16065
Does your table have a unique synthetic ID - a primary key that is always increased when inserting new row ? Usually there is one. And then the largest IDs would correspond to latest purchases typically (unless you have offline purchases that you insert into your DB long after the fact).So, usually (not always) you can instead look for max(ID) per good, not max(date). This has a bonus that you would not have two rows with the same ID while you can have to rows with the same date.... In the latter case you would unexpectedly get several rows per good and your program would puke
So, from this point on I would assume that those are true: 1) in your tables you have a typical integer PRIMARY-KEY column ID, filled with generator(aka sequence), so that the row inserted later would always have its ID larger. 2) you insert purchase records as those purchases are done, immediately. You do not sell when offline and you do not later batch-insert accumulated data that already is few hours/days old.
actually, your ReceiptNum
might be like that id, if you do not reset it to 1 every year or every month. But usually real-world document numbers are getting resetted on timely matter, so the synthetic ID is preferred for linking tables together
In this case getting last records per-good is rather simple:
SELECT MAX(ID), ItemName from PurchaseReceiptLines group by ItemName
granted, this does not give you dates and quantities, because it is a "totalling" request.
SELECT PRL_Data.ID, PRL_Data.ItemName, prh.Receiptdate, PRL_Data.ReceiptQuantity
FROM PurchaseReceiptLines PRL_Data
JOIN (SELECT MAX(ID) as ID, ItemName from PurchaseReceiptLines group by ItemName) PRL_Max
ON PRL_Max.ID = PRL_Data.ID
JOIN PurchaseReceiptHeader prh
ON prh.ID = PRL_Data.Header_ID /* like prh.ReceiptNum = prl.ReceiptNum but with never resetting */
Upvotes: 0
Reputation: 1
select im.itemname, max(prh.receiptdate),
(select prl.receiptquantity from purchasereceiptlines prl
join purchasereceiptheader prh on prh.receiptnum = prl.receiptnum
where prl.itemname = im.itemname)
from itemmaster im
left join purchasereceiptlines prl on prl.itemname = im.itemname
left join purchasereceiptheader prh on prh.receiptnum = prl.receiptnum
group by im.itemname
Upvotes: 0
Reputation: 1270553
Firebird 3.0 supports window functions. In that case, row_number()
is the right approach. In older versions:
with i as (
select im.ItemName, prh.Receiptdate, prl.ReceiptQuantity
from ItemMaster im left join
PurchaseReceiptLines prl
on prl.ItemName = im.ItemName left join
PurchaseReceiptHeader prh
on prh.ReceiptNum = prl.ReceiptNum
)
select i.*
from i
where i.Receiptdate = (select i2.Receiptdate from i i2 where i2.ItemName = i.ItemName);
Upvotes: 1