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

发布于 2024-10-01 23:44:56 字数 1121 浏览 4 评论 0原文

我一直想弄清楚如何编写查询。基本上我有三个表(订单、产品、订单_产品),我想将它们连接在一起并应用一些过滤。

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。

I'm stuck to figure out how to write a query. Basically I've three tables (Orders, Products, Orders_Products) which I want to join together and apply some filtering.

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

For example I want to get all Orders which consists (exactly) of the products P1/T1 and P2/T3. I tried something like this, but that doesn't work:

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

EDIT: To clarify what I really have to achieve. The user should be able to search for orders matching the given products. The user enters one or more product name / product title combinations and gets all the orders which have exactly this products associated. What I get (from a web application) are only the name/title combinations and I have to use those in a query to get the ORDER_ID.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心的憧憬 2024-10-08 23:44:56
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

我想这应该会让您的订单这两种产品。

SELECT OrderID, COUNT(*) AS ProductsCount
FROM Orders_Products
WHERE (PRODUCT_ID = 1 OR PRODUCT_ID = 3)
GROUP BY OrderID
HAVING COUNT(*) = 2

EDIT: Please ignore the above statement. See if the following works.

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

I guess this should get you Orders which has only these 2 products.

请别遗忘我 2024-10-08 23:44:56

您可能无法在 MySQL 中编写简单的查询来实现此目的。但 ANSI SQL 支持表值构造函数,这简化了此类查询。

此基本查询返回订单的完整列表(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

此带有表值构造函数的查询返回您需要的订单:

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

开源数据库中,HSQLDB是支持表值构造函数的数据库以及 ANSI SQL:2008 的其他用户友好功能

You probably cannot write simple queries in MySQL to achieve this. But ANSI SQL supports table value constructor which simplifies this type of query.

This basic query returns the full list of orders (5 rows):

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

This query with table value constructor returns the orders that you need:

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

This query groups the above to returns the ORDER_ID where there is no order outside the required list (eliminating the orders that have rows containing 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

Among open source databases, HSQLDB is one that supports table value constructor and other user friendly features of ANSI SQL:2008

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文