I am struggling to get my head around this sql.
I have a function that returns a list of items associated with a Bill of Materials BOM.
The result of the sql select
SELECT
BOM,
ITEMID,
QTY
FROM boms
WHERE
bom='A'
is
BOM | ITEMID | QTY
A | ITEMB | 1
A | ITEMC | 2
Now using that result set I am looking to query my salestable to find sales where ITEMB and ITEMC were sold in enough quantity.
The format of the salestable is as follows
SELECT
salesid,
itemid,
sum(qtyordered) 'ordered'
FROM salesline
WHERE
itemid='ITEMB'
or itemid='ITEMC'
GROUP BY salesid, itemid
This would give me something like
salesid | itemid | ordered
SO-10000 | ITEMB | 1
SO-10001 | ITEMB | 1
SO-10001 | ITEMC | 1
SO-10002 | ITEMB | 1
SO-10002 | ITEMC | 2
ideally I would like to return only SO-10002 as this is the only sale where all necessary units were sold.
Any suggestions would be appreciated. Ideally one query would be ideal but I am not sure if that is possible. Performance is not a must as this would be run once a week in the early hours of the morning.
EDIT
with the always excellent help, the code is now complete. I have wrapped it all up into a UDF which simply returns the sales for a specified BOM over a specified period of time.
Function is
CREATE FUNCTION [dbo].[BOMSALES] (@bom varchar(20),@startdate datetime, @enddate datetime)
RETURNS TABLE
AS
RETURN(
select count(q.SALESID) SOLD FROM (SELECT s.SALESID
FROM
(
SELECT s.SALESID, ITEMID, SUM(qtyordered) AS SOLD
FROM salesline s inner join SALESTABLE st on st.salesid=s.SALESID
where st.createddate>=@startdate and st.CREATEDDATE<=@enddate and st.salestype=3
GROUP BY s.SALESID, ITEMID
) AS s
JOIN dbo.BOM1 AS b ON b.ITEMID = s.ITEMID AND b.QTY <= s.SOLD
where b.BOM=@bom
GROUP BY s.SALESID
HAVING COUNT(*) = (SELECT COUNT(*) FROM dbo.BOM1 WHERE BOM = @bom)) q
)
This should return all sales with an exact match, i.e. same itemid and same quantity:
SELECT s.salesid
FROM
(
SELECT salesid, itemid, SUM(qtyordered) AS ordered
FROM salesline AS s
GROUP BY salesid, itemid
) AS s
JOIN
boms AS b
ON b.itemid = s.itemid
AND b.QTY = s.ordered
WHERE b.BOM='A'
GROUP BY s.salesid
HAVING COUNT(*) = (SELECT COUNT(*) FROM boms WHERE BOM='A');
If you want to return a sale where the quantity is greater than boms.qty youhave to change the join accordingly:
JOIN
boms AS b
ON b.itemid = s.itemid
AND b.QTY <= s.ordered
Untested...