2015-04-07 2 views
3

Я искал это, но не нашел ничего особенного.SQL ALL IN статья

Возможно ли иметь SQL-запрос, который будет действовать как ALL IN? Чтобы лучше объяснить, вот структура таблицы.

Orders table 
OrderItem table (having several columns, but mainly ProductID, OrderID) 
ProductGroup table (several columns, but mainly GroupID and ProductID) 

Я хочу написать запрос, который выберет весь заказ, относящийся к определенной ProductGroup. Поэтому, если у меня есть группа с именем «XYZ» с ID = 10. В ней есть один ProductID. Say ProductID01

В комплект поставки заказа входит заказ. ProductID01 и ProductID02. Для того, чтобы найти все заказы в конкретной группе товаров можно использовать простой SQL как

SELECT bvc_OrderItem.ProductID, bvc_OrderItem.OrderID 
From bvc_OrderItem 
INNER JOIN bvc_Product_Group_Product with (nolock) ON bvc_OrderItem.ProductID = bvc_Product_Group_Product.ProductID 
WHERE bvc_Product_Group_Product.GroupID = 10 

Или я могу написать, используя в пункте

SELECT bvc_OrderItem.ProductID, bvc_OrderItem.OrderID 
From bvc_OrderItem 
WHERE ProductID IN (
    SELECT ProductID FROM bvc_Product_Group_Product WHERE GroupID=10 
) 

Однако, Это возвращает все заказы, где один или несколько ProductIDs являются частью группы продуктов. Мне нужно вернуть строку заказа ТОЛЬКО, если ВСЕ элементы заказа являются частью группы продуктов

Так что, в основном, мне нужен элемент IN, который будет считаться согласованным, если ВСЕ значения внутри IN IN совпадают с строками в bvc_OrderItem.

Или, если мы используем Join, то объединение должно выполняться только в том случае, если ВСЕ строки слева имеют значения в соответствующей правой таблице.

Если бы я мог записать его более просто, я бы записать его как этот

Select ID FROM Table WHERE ID IN (1, 2, 3, 4) 

и если таблица содержит все строки с идентификаторами 1,2,3,4; он должен вернуть успех. Если какой-либо из этих значений IN отсутствует, он должен возвращать значение false, и ничего не следует выбирать.

Как вы думаете, это возможно? Или есть обходное решение для этого?

+0

Может быть, вы должны перефразировать свое состояние как " ордеров, для которых не существует строк, которые не принадлежат группе X '? – Arvo

+1

Это звучит как [реляционное деление] (https://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/) –

+0

Я не знаю, я понимаю, что вы пытаетесь найти. Есть заказы, состоящие из одного или нескольких предметов, каждый из которых является продуктом, который существует в группе. Таким образом, ваше утверждение «Найти все заказы в конкретной группе продуктов ...» не имеет смысла. Заказы не связаны с группами продуктов. Вы имеете в виду для заказа, который состоит из продукта P, принадлежащего группе G, вы хотите видеть все остальные заказы, которые состоят только из продуктов группы G? Или вы хотите видеть все заказы, которые состоят из * любого * продукта группы G? Что вы ищете? – TommCatt

ответ

3

Вы можете получить список заказов в различных формах, таких как:

SELECT oi.OrderID 
FROM bvc_OrderItem oi JOIN 
    bvc_Product_Group_Product pgp 
    ON oi.ProductID = pgp.ProductId AND 
     pgp.GroupID = 10 
GROUP BY oi.OrderID 
HAVING COUNT(DISTINCT oi.ProductID) = (SELECT COUNT(*) 
             FROM bvc_Product_Group_Product 
             WHERE GroupID = 10 
            ); 

Получение конкретных продуктов требует дополнительного join. В большинстве случаев список заказов более полезен.

Проблема с вашим синтаксисом ALL IN заключается в том, что он не делает то, что вы хотите. Вы хотите выбрать заказов. Синтаксис:

SELECT bvc_OrderItem.ProductID, bvc_OrderItem.OrderID 
From bvc_OrderItem 
WHERE ProductID ALL IN (SELECT ProductID 
         FROM bvc_Product_Group_Product 
         WHERE GroupID = 10 
         ) 

Это не указует, что вы собираетесь для группировки, чтобы быть по OrderId, в отличие от какого-то другого уровня.

Более фундаментально, однако, язык SQL вдохновлен реляционной алгеброй. Конструкции SELECT, JOIN, WHERE и GROUP BY непосредственно связаны с фундаментальными конструкциями реляционной алгебры. Понятие ALL IN - хотя иногда полезно - может быть выражено с использованием более основных строительных блоков.

+0

WHERE ProductID ALL IN ...... Какая версия SQL-сервера работает? Я уже пробовал это в 2008 и 2008 годах, но это, похоже, не является допустимым вариантом для них. –

+0

Кроме того, с использованием операции группировки с количеством (DISTINCT oi.Product), это может не сработать. Так как группа продуктов может содержать 100 Продуктов, а заказ может содержать два или четыре элемента. Мы должны убедиться, что элементы заказа являются частью группы продуктов. Поэтому, если оба или все элементы заказа являются частью группы продуктов, мы будем рассматривать его как совпадение. Если какой-либо из них НЕ является частью группы, мы будем рассматривать его как НЕ-МАТЧ. Спасибо –

0

Вы можете сделать это с помощью этого хитрого заявления:

DECLARE @Items TABLE 
    (
     OrderID INT , 
     ProductID INT 
    ) 
DECLARE @Groups TABLE 
    (
     ProductID INT , 
     GroupID INT 
    ) 

INSERT INTO @Items 
VALUES (1, 1), 
     (1, 2), 
     (2, 1), 
     (3, 3), 
     (3, 4) 

INSERT INTO @Groups 
VALUES (1, 10), 
     (2, 10), 
     (3, 10), 
     (4, 15) 


SELECT OrderID 
FROM @Items i 
GROUP BY OrderID 
HAVING (CASE WHEN 10 = ALL (SELECT gg.GroupID 
           FROM  @Items ii 
             JOIN @Groups gg ON gg.ProductID = ii.ProductID 
           WHERE ii.OrderID = i.OrderID) THEN 1 
       ELSE 0 
      END) = 1 

Выход:

OrderID 
1 
2 

Кроме того (это лучше):

SELECT OrderID 
FROM @Items i 
     JOIN @Groups g ON g.ProductID = i.ProductID 
GROUP BY OrderID 
HAVING MIN(g.GroupID) = 10 
     AND MAX(g.GroupID) = 10 
+0

Привет, Спасибо за ваш ответ. Однако он вернет true, если даже один Продукт принадлежит группе. мы нуждаемся в этом, если ВСЕ товары принадлежат группе. Я тестировал его, и он возвращает orderid, даже если One ProductID принадлежит к группе продуктов. Нам нужно, чтобы он не возвращал OrderID, если к группе принадлежит только один элемент. Но только тогда, когда все элементы заказа (ProductIds) принадлежат группе. –

+0

@SameersJaved, вы не правы. В моих данных есть Order = 3 с 2 продуктами (3, 4) 3 - группа 10 и 4 - группа 15. Заказ = 3 не возвращается с моим запросом. –