如何根据子选择将表连接在一起?

时间:2010-11-12 10:02:48

标签: sql join subquery

我很想弄清楚如何编写查询。基本上我有三个表(订单,产品,订单_产品),我想加入并应用一些过滤。

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');

编辑:澄清我真正需要实现的目标。用户应该能够搜索与给定产品匹配的订单。用户输入一个或多个产品名称/产品标题组合,并获得与该产品完全关联的所有订单。我得到的(来自Web应用程序)只是名称/标题组合,我必须在查询中使用它们来获取ORDER_ID。

2 个答案:

答案 0 :(得分:1)

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

我想这应该可以为您提供这两种产品的订单。

答案 1 :(得分:0)

您可能无法在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,其中所需列表之外没有订单(消除包含null的行的订单):

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