Как объединить таблицы на основе подвыборов? - PullRequest
1 голос
/ 12 ноября 2010

Я застрял, чтобы выяснить, как написать запрос.В основном у меня есть три таблицы (Заказы, Продукты, Заказы_Продукты), которые я хочу объединить и применить некоторую фильтрацию.

Orders table:
  ORDER_ID   CUSTOMER_ID
  1          1
  2          2

Products table:
  PRODUCT_ID   PRODUCT_NAME    PRODUCT_TITLE
  1            'P1'            'T1'
  2            'P1'            'T2'
  3            'P2'            'T3'
  4            'P2'            'T4'
  5            'P2'            'T5'
  6            'P3'            'T6'

Orders_Products table:
  ORDER_ID   PRODUCT_ID
  1          1
  1          3
  2          1
  2          3
  2          6

Например, я хочу получить все Заказы, которые состоят (точно) из продуктов P1/ T1 и P2 / T3.Я пытался что-то вроде этого, но это не работает:

SELECT * FROM Orders
LEFT JOIN Orders_Products ON Orders_Products.ORDER_ID = Orders.ORDER_ID
LEFT JOIN Products ON Orders_Products.PRODUCT_ID = Products.PRODUCT_ID
WHERE EXISTS (SELECT * FROM Product WHERE PRODUCT_NAME = 'P1' AND PRODUCT_TITLE = 'T1')
AND EXISTS (SELECT * FROM Product WHERE PRODUCT_NAME = 'P2' AND PRODUCT_TITLE = 'T3');

РЕДАКТИРОВАТЬ: Чтобы уточнить, чего я действительно должен достичь.Пользователь должен иметь возможность искать заказы, соответствующие данным продуктам.Пользователь вводит одну или несколько комбинаций названия продукта / названия продукта и получает все заказы, с которыми связан именно этот продукт.То, что я получаю (из веб-приложения) - это только комбинации имени и названия, и мне нужно использовать их в запросе, чтобы получить ORDER_ID.

Ответы [ 2 ]

1 голос
/ 12 ноября 2010
SELECT OrderID, COUNT(*) AS ProductsCount
FROM Orders_Products
WHERE (PRODUCT_ID = 1 OR PRODUCT_ID = 3)
GROUP BY OrderID
HAVING COUNT(*) = 2

РЕДАКТИРОВАТЬ: Пожалуйста, игнорируйте приведенное выше утверждение. Посмотрите, работает ли следующее.

SELECT OrderID, 
SUM(CASE PRODUCT_ID WHEN 1 THEN 1 WHEN 3 THEN 1 ELSE 3 END)
AS ProductsCount
FROM Orders_Products
GROUP BY OrderID
HAVING SUM(CASE PRODUCT_ID WHEN 1 THEN 1 WHEN 3 THEN 1 ELSE 3 END) = 2

Полагаю, это должно принести вам заказы, в которых только эти 2 продукта

0 голосов
/ 12 ноября 2010

Вы, вероятно, не можете написать простые запросы в MySQL для достижения этой цели. Но ANSI SQL поддерживает table value constructor, что упрощает этот тип запроса.

Этот базовый запрос возвращает полный список заказов (5 строк):

SELECT * FROM Products 
JOIN Orders_Products ON Orders_Products.PRODUCT_ID = Products.PRODUCT_ID
JOIN Orders ON Orders_Products.ORDER_ID = Orders.ORDER_ID

Этот запрос с table value constructor возвращает нужные вам заказы:

SELECT * FROM Products 
JOIN Orders_Products ON Orders_Products.PRODUCT_ID = Products.PRODUCT_ID
JOIN Orders ON Orders_Products.ORDER_ID = Orders.ORDER_ID 
LEFT JOIN (VALUES('P1', 'T1'), ('P2', 'T3')) V(P_NAME, P_TITLE) ON PRODUCT_NAME = P_NAME AND PRODUCT_TITLE=P_TITLE

Этот запрос группирует вышеприведенный запрос, возвращая ORDER_ID, в котором нет порядка вне требуемого списка (исключая ордера, в которых есть строки, содержащие ноль):

SELECT ORDER_ID FROM Products 
JOIN Orders_Products ON Orders_Products.PRODUCT_ID = Products.PRODUCT_ID
JOIN Orders ON Orders_Products.ORDER_ID = Orders.ORDER_ID 
LEFT JOIN (VALUES('P1', 'T1'), ('P2', 'T3')) V(P_NAME, P_TITLE) ON PRODUCT_NAME = P_NAME AND PRODUCT_TITLE=P_TITLE
GROUP BY ORDER_ID HAVING COUNT(*) = 2

Среди баз данных с открытым исходным кодом HSQLD B - это та, которая поддерживает конструктор табличных значений и другие удобные функции ANSI SQL: 2008

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...