2014-08-29 3 views
2

У меня есть две таблицы. Таблица продаж, содержащая номера счетов, номера деталей и количества и таблицу Bundles, содержащие идентификатор пакета, номера и количества деталей. Например:SQL Relational Division с дополнительными критериями

продаж:

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 комплект 2).

Я использую MS ACCESS для этих данных.

+0

В вашем запросе используется поле «BID», но такого поля в таблице пакетов нет. Существует поле под названием «ID». Какой из них правильный? –

+0

Как вы знаете, счет 001 содержит пакет 1? Связан ли BundleId с InvoiceId? Либо таблица связок реплицирует информацию из таблицы счетов, либо есть другая таблица, которая объединяет эти 2 объекта (или должна быть, если их нет) –

+0

Я предполагаю, что фактический способ определить, связан ли счет-фактура с конкретным пакетом что в комплекте содержатся все совпадающие значения part_no счета-фактуры? Хотя это далеко и далеко от того, что делает ваш текущий запрос. –

ответ

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»), тогда это подсчитало бы, что достаточно одного и того же участка, чтобы удовлетворить пакет Bundle 1 & Bundle 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 

Но для того, чтобы действительно удовлетворить ОБА Связки должно быть 2 каждого «ааа» и «ссс». Если требуется этот уровень детализации, потребуются дополнительные критерии. Если нет, то не делайте его более сложным, чем это должно быть. Вот SQL Fiddle, содержащий дополнительную строку.

+0

Hmm, doesn «Неплохо. Этот запрос возвращает BID 1 и 2 для счетов 1, 2 и 3 для счета-фактуры 2 и 2 для счета-фактуры 3 –

+0

Следующий запрос работает для BID 1, но странно не для BID 2 SELECT S.Invoice_No, 1 как Bundle From Sales as S INNER JOIN (SELECT BID, Part_No, QTY FROM Bundles WHERE BID = 1) как B ON S.Part_No = B.Part_No AND S.QTY> = B.QTY GROUP BY S.Invoice_No ИМЕЕТ СЧЕТ (S.Part_No) = (SELECT count (Part_No) FROM Связки WHERE BID = 1) –

+0

Вы пытались использовать SQL Fiddle или против вашего набора данных? –

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 
         ) 
       ) 
     ) 
     ; 
Смежные вопросы