I'm currently working on a Firebird database where the product to product cost table is one to many. I need to include the most current cost (highest ID) in product listing script.
I'm not sure how to do this on a one to many relation.
select SPLU.SHOPPRODUCTSPLUID,SPLU.plu, SPLU.description, SPLU.SHOPPRODUCTSID,
SG.GROUPNAME, SCOST.NORMALCOST, splu.sellprice1, SSL.NAME as fmSuppliername,
sdl.NAME as fmDeptName,SS.MAINSUPPLIER as fmMainSupplier, SS.UNITSPERCARTON as UPC
from SHOPPRODUCTSPLU SPLU
join SHOPPRODUCTS SP
on SP.SHOPPRODUCTSID = SPLU.SHOPPRODUCTSID
join SHOPGROUPLOOKUP SG
on SG.SHOPGROUPLOOKUPID = SP.SHOPGROUPLOOKUPID and SP.STOREID = SG.STOREID
join SHOPSUPPLIER SS
on SS.SHOPPRODUCTSID = SP.SHOPPRODUCTSID and SS.STOREID = SP.STOREID
JOIN SHOPSUPPLIERLOOKUP SSL
ON SSL.SHOPSUPPLIERLOOKUPID = SS.SHOPSUPPLIERLOOKUPID
join SHOPDEPTLOOKUP SDL
ON SDL.SHOPDEPTLOOKUPID = SG.SHOPDEPTLOOKUPID
join SHOPPRODUCTSCOSTHST SCOST
on SCOST.SHOPPRODUCTSID = SPLU.SHOPPRODUCTSID
where SP.STOREID = 1 and SPLU.ACTIVEITEM = 'TRUE' and SP.ACTIVEITEM = 'TRUE'
My join on SHOPPRODUCTSCOSTHST will now bring in a record for every cost in the table below when we only need the newest.
Current output
One solution would be to add a condition to the join on SHOPPRODUCTSCOSTHST
that filters on the matching record that has the highest id:
join SHOPPRODUCTSCOSTHST SCOST
on SCOST.SHOPPRODUCTSID = SPLU.SHOPPRODUCTSID
and SCOST.SHOPPRODUCTSCOSTHSID = (
select max(SCOST1.SHOPPRODUCTSCOSTHSID)
from SHOPPRODUCTSCOSTHST SCOST1
where SCOST1.SHOPPRODUCTSID = SPLU.SHOPPRODUCTSID
)
If SHOPPRODUCTSCOSTHSID
is a unique key in table SHOPPRODUCTSCOSTHST
, this can be simplified a little:
join SHOPPRODUCTSCOSTHST SCOST
on SCOST.SHOPPRODUCTSCOSTHSID = (
select max(SCOST1.SHOPPRODUCTSCOSTHSID)
from SHOPPRODUCTSCOSTHST SCOST1
where SCOST1.SHOPPRODUCTSID = SPLU.SHOPPRODUCTSID
)
For performance here, you want an index on SCOST(SHOPPRODUCTSID, SHOPPRODUCTSCOSTHSID)
.
One possible solution is to use a CTE.
Some factors in which you wouldn't want to use the method i am proposing is if your SHOPPRODUCTSCOSTHST table has a large number of rows. Another factor would be if this query is executed very frequently.
The CTE would be used to get the MAX ID of SHOPPRODUCTSCOSTHST grouped by SHOPPRODUCTSID. Then I would use that CTE in the main query and constrain your INNER JOIN SCOST on CTE.MAX_SHOPPRODUCTSCOSTHSTID = SCOST.SHOPPRODUCTSCOSTHSTID. That would return only one row per SHOPPRODUCTSID.
below is an example.
WITH MAXCOSTHST
AS (
SELECT SHOPPRODUCTSID
,MAX(SHOPPRODUCTSCOSTHSTID) MAX_SHOPPRODUCTSCOSTHSTID
FROM SHOPPRODUCTSCOSTHST
GROUP BY SHOPPRODUCTSID
)
SELECT SPLU.SHOPPRODUCTSPLUID
,SPLU.plu
,SPLU.description
,SPLU.SHOPPRODUCTSID
,SG.GROUPNAME
,SCOST.NORMALCOST
,splu.sellprice1
,SSL.NAME AS fmSuppliername
,sdl.NAME AS fmDeptName
,SS.MAINSUPPLIER AS fmMainSupplier
,SS.UNITSPERCARTON AS UPC
FROM SHOPPRODUCTSPLU SPLU
JOIN SHOPPRODUCTS SP ON SP.SHOPPRODUCTSID = SPLU.SHOPPRODUCTSID
JOIN SHOPGROUPLOOKUP SG ON SG.SHOPGROUPLOOKUPID = SP.SHOPGROUPLOOKUPID
AND SP.STOREID = SG.STOREID
JOIN SHOPSUPPLIER SS ON SS.SHOPPRODUCTSID = SP.SHOPPRODUCTSID
AND SS.STOREID = SP.STOREID
JOIN SHOPSUPPLIERLOOKUP SSL ON SSL.SHOPSUPPLIERLOOKUPID = SS.SHOPSUPPLIERLOOKUPID
JOIN SHOPDEPTLOOKUP SDL ON SDL.SHOPDEPTLOOKUPID = SG.SHOPDEPTLOOKUPID
JOIN MAXCOSTHST ON MAXCOSTHST.SHOPPRODUCTSID = SPLU.SHOPPRODUCTSID
JOIN SHOPPRODUCTSCOSTHST SCOST ON SCOST.SHOPPRODUCTSID = SPLU.SHOPPRODUCTSID
AND MAXCOSTHST.MAX_SHOPPRODUCTSCOSTHSTID = SCOST.SHOPPRODUCTSCOSTHSTID
WHERE SP.STOREID = 1
AND SPLU.ACTIVEITEM = 'TRUE'
AND SP.ACTIVEITEM = 'TRUE'
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.