SQL关系部门有其他标准

时间:2014-08-29 04:12:10

标签: sql ms-access relational-division

我有两张桌子。包含发票编号,部件号和数量的销售表以及捆绑包表,包含捆绑包ID,部件号和数量。 E.g:

销售:

Invoice_No | Part_No | QTY
-----------------------------
1          |aaa      |1
1          |bbb      |2
1          |ccc      |1
2          |aaa      |1
2          |ccc      |1
2          |ddd      |2
3          |aaa      |1
3          |bbb      |1
3          |ccc      |1

软件包:

BID | Part_No | QTY
-------------------
1   |aaa      |1
1   |bbb      |2
1   |ccc      |1
2   |aaa      |1
2   |ccc      |1
2   |ddd      |1

我想要一个查询来识别包含给定捆绑包中至少具有所需数量的所有部件的发票。

即。发票001包含捆绑包1  和发票002包含捆绑2

通过查看这里的示例,我已经能够获得部分路径: https://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/

SELECT S.Invoice_No, 1 as Bundle From Sales as S
INNER JOIN (SELECT BID, Part_No, QTY FROM Bundles WHERE BID=1) as B
ON S.Part_No=B.Part_No
GROUP BY S.Invoice_No
HAVING COUNT(S.Part_No)=(SELECT count(Part_No) FROM Bundles WHERE BID=1)

但是,此查询错误地将发票3识别为具有捆绑包1.我还希望不必为每个捆绑包提出单独的查询,因为这样会在将来添加更多捆绑包时耗费时间。

作为扩展程序,我还希望能够识别包含多个捆绑包的发票(例如,发票可能包含2个捆绑包1,或1个捆绑包1和1个捆绑包2)。

我正在使用MS ACCESS获取此数据。

2 个答案:

答案 0 :(得分:1)

-- the data
CREATE TABLE sales
        ( seq SERIAL NOT NULL PRIMARY KEY
        , invoice_no INTEGER NOT NULL
        , part_no CHAR(3) NOT NULL
        , qty INTEGER NOT NULL DEFAULT 0
        );
INSERT INTO sales (invoice_no, part_no, qty) VALUES
 (1, 'aaa' ,1 ) ,(1, 'bbb' ,2 ) ,(1, 'ccc' ,1 )
,(2, 'aaa' ,1 ) ,(2, 'ccc' ,1 ) ,(2, 'ddd' ,2 )
,(3, 'aaa' ,1 ) ,(3, 'bbb' ,1 ) ,(3, 'ccc' ,1 )
        ;

CREATE TABLE bundles
        (seq SERIAL NOT NULL PRIMARY KEY
        , bid INTEGER NOT NULL
        , part_no CHAR(3) NOT NULL
        , qty INTEGER NOT NULL DEFAULT 0
        );

INSERT INTO bundles(bid, part_no, qty) VALUES
 (1, 'aaa' ,1) , (1, 'bbb' ,2) , (1, 'ccc' ,1)
, (2, 'aaa' ,1) , (2, 'ccc' ,1) , (2, 'ddd' ,1)
        ;

SELECT * FROM sales;
SELECT * FROM bundles;


        -- find the orders
SELECT * FROM sales sa
WHERE EXISTS (  -- sales is part of some bundles
                -- find all bundles containing the articles in these orders
        SELECT * FROM bundles bu
        WHERE bu.part_no = sa.part_no
        AND NOT EXISTS ( -- this bundle MUST contain ALL items from this order
                         -- ==>> bundle MUST NOT contain ANY item NOT in this order
                         -- (or in too low qty)
                SELECT *
                FROM bundles xb
                WHERE xb.bid = bu.bid
                AND NOT EXISTS ( -- 
                        SELECT * FROM sales xs
                        WHERE xs.part_no = xb.part_no
                        AND xs.invoice_no = sa.invoice_no
                        AND xs.qty >= xb.qty
                        )
                )
        )
        ;

答案 1 :(得分:0)

以下情况应根据您的数据集进行(除非我有一些字段名称错误)

SELECT S.Invoice_No, B.BID, count(S.part_no)
FROM SALES as S
INNER JOIN Bundle as B ON S.Part_No = B.Part_No AND S.qty >= B.qty
GROUP BY S.INVOICE_no, B.BID
HAVING COUNT(S.Part_No) >= (SELECT count(B2.Part_No) 
                            FROM Bundle B2 
                            WHERE B2.BID = B.BID)

SQL Fiddle

如果您预计每次促销不超过一个捆绑包,上述内容适用于简单的情况。如果一个额外的项目被添加到发票1(即单个' ddd'),那么这将计算出在相同的部件上有足够的满足捆绑1&捆绑2 - 因为它不包括其他捆绑包。

示例:

INSERT INTO SALES VALUES (1, 'aaa', 1);  -- satisfies Bundle 1 and Bundle 2
INSERT INTO SALES VALUES (1, 'bbb', 2);  -- satisfies Bundle 1
INSERT INTO SALES VALUES (1, 'ccc', 1);  -- satisfies Bundle 1 and Bundle 2
INSERT INTO SALES VALUES (1, 'ddd', 1);  -- satisfies Bundle 2

但是为了真正满足BOTH Bundles,每个应该有两个' aaa'和' ccc'。如果需要这种详细程度,则需要其他标准。如果没有,那就不要让它变得比它需要的更复杂。这是包含附加行的SQL Fiddle