Search code examples
sqlsql-server-2000

sql 2000 select id where multiple row conditions are met


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
)

Solution

  • 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...