如何为订单及其项目编写自定义 MySQL select 查询

How to write custom MySQL select query for orders and their items

我已尽我所能尽可能完整地描述我的问题;如果您有任何问题,请发表评论并提问。我知道我可能错过了一个非常简单的解决方案,并且很想听听如何使它更简单;也就是说,请确保您的回答考虑了我所描述的所有内容,并且在发布您的解决方案之前您已经提出了所有问题(并收到了答案)。

背景

两个 table:ordersitems,每个都包含唯一的信息(它们使用 ID 相互连接;没有重复数据)。请参阅附件 A 和 B(下方)。

orders table(附件 A)包含该订单的所有独特信息。添加到订单的每个项目在 table 中都有自己的行,其中包含订单 ID、项目 ID 和数量(以及其他不相关的字段)。

问题

我正在构建一个界面,允许用户通过以下参数过滤订单:

在我看来,在单个 MySQL 查询中收集所有数据应该是可能的。这是我需要收集的信息:

例子

用户希望按以下规格过滤所有订单:

如果所有数据(订单和项目)都包含在一个 table 中,查询将是这样的:

SELECT order_ID, 
       GROUP_CONCAT(item_ID) as item_IDs, 
       GROUP_CONCAT(quantity) as quantities, 
       SUM(price) as price 
FROM orders 
GROUP BY order_ID 
HAVING 7 = SUM(quantity) AND 
       3 = COUNT(*)

和 return 是这样的:

order_ID | item_IDs | quantities | price
=========================================
15       | 22,9,36  | 1,4,2      | 2

但由于价格存储在单独的 table 中,因此比较复杂。我创建了这个查询(参见图表 C):

SELECT DISTINCT o.order_ID, 
       GROUP_CONCAT(o.`item_ID`) as item_IDs,
       GROUP_CONCAT(o.`quantity`) as quantities 
FROM orders o 
GROUP BY o.`order_ID` 
HAVING 7 = SUM(o.`quantity`) AND 
       3 = COUNT(*) 
ORDER BY o.`order_ID` DESC`

这让我很接近,但让我想要定价信息。我试过使用 JOINS (What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?),但几个小时后无法正常工作。

问题

是否可以在一个 MySQL 查询中检索所有这些数据,and/or 有没有比我目前所走的路径更好的方法(你会怎么做)?

接受table 查询 return 结果类似于:

order_ID | item_ID | quantity | price
======================================
177      | 42      | 2        | 50.00
177      | 45      | 3        | 30.00
177      | 46      | 2        | 10.00
150      | 39      | 3        | 25.00
150      | 47      | 1        | 95.00
150      | 41      | 3        | 15.00

只要查询要求生成的订单包含 3 件商品和 7 件商品,并且总计少于 600 美元(根据提供的示例)。

我也很遗憾这在一个查询中可能无法实现,并且我知道如何使用 PHP 来完成此操作;我想我可能会尝试在 MySQL 中尽可能多地做这件事,并在今天学到一些东西。 :)

你们中的一些人可能会建议更改 table 结构,但我真的不想让 table 包含重复数据,如果有帮助的话:如果产品价格发生变化,我宁愿不必在 table 秒后更新。

感谢您抽出宝贵时间以及您可能有的任何解决方案;我非常感谢你们能提供的任何帮助。

Exhibits/Visual 艾滋病

图表 A:ordersTable

ID    | order_ID | item_ID | quantity
======================================
1146  | 195      | 52      | 3
1145  | 195      | 1       | 4
1142  | 193      | 41      | 1
1141  | 193      | 40      | 3
1031  | 177      | 45      | 3
1032  | 177      | 46      | 2
1030  | 177      | 42      | 2
881   | 150      | 47      | 1
880   | 150      | 39      | 3
882   | 150      | 41      | 3

图表 B:itemsTable

(为完整性提供,而非关键信息) https://cldup.com/ZQEDy-vef6.png

图表 C:查询和结果

SELECT DISTINCT o.order_ID, 
       GROUP_CONCAT(o.`item_ID`) as item_IDs,
       GROUP_CONCAT(o.`quantity`) as quantities 
FROM orders o 
GROUP BY o.`order_ID` 
HAVING 7 = SUM(o.`quantity`) AND 
       3 = COUNT(*) 
ORDER BY o.`order_ID` DESC

.

order_ID | item_IDs | quantities
=================================
177      | 42,45,46 | 2,3,2
150      | 39,47,41 | 3,1,3
115      | 39,47,41 | 3,1,3
108      | 48,45,46 | 2,3,2

图表 D:SQLFiddle

http://sqlfiddle.com/#!9/2763f5

我就从这里开始,一步步完成。

首先是 LEFT JOIN 是你的朋友。这样就可以得到每件商品的价格

示例 1:

通过此查询,您可以获得 table 个订单的前 100 行,包括每个订单的价格。

SELECT o.order_ID, 
       o.item_ID as item_ID,
       o.quantity as quantitie,
       i.price
FROM orders o
LEFT JOIN items i ON o.item_ID = i.id
ORDER BY o.order_ID
LIMI 100;

示例 2:

现在您的查询必须分成两部分。首先,我们将获得所有符合您的标准(商品、件数和价格)的订单 ID

     SELECT o.order_ID
        FROM orders o
        LEFT JOIN items i ON o.item_ID = i.id
        GROUP BY o.order_ID
        HAVING
         SUM(o.`quantity`) =7 
       AND
         SUM(1) = 3
       AND
         SUM(i.price) < 700;
       ORDER BY o.order_ID;

示例 3:

现在他拥有所有 order_ids 并且可以合并两个查询。

SELECT o.order_ID, 
       o.item_ID as item_ID,
       o.quantity as quantitie,
       i.price
FROM orders o
LEFT JOIN items i ON o.item_ID = i.id
where o.order_ID IN (
    SELECT o.order_ID
    FROM orders o
    LEFT JOIN items i ON o.item_ID = i.id
    GROUP BY o.order_ID
    HAVING
     SUM(o.`quantity`) =7 
   AND
     SUM(1) = 3
   AND
     SUM(i.price) < 700    )
ORDER BY o.order_ID, o.quantity, i.price;

但是这不是testet。如果您通过 sqlfidle 放置一些示例日期,那么我可以直接为您测试它。

示例 4

我已将最后一个查询更改为 LEFT JOINS,但它不适用于 fiddle。我超时了。请检查您的服务器。

我还看到您的表上没有好的索引。所以查询会非常慢

  SELECT mo.order_ID, 
        mo.item_ID ,
        mo.quantity,
        mi.price
   FROM (
        SELECT o.order_ID
        FROM orders o
        LEFT JOIN items i ON o.item_ID = i.id
        GROUP BY o.order_ID
        HAVING
         SUM(o.`quantity`) =7 
       AND
         SUM(1) = 3
       AND
         SUM(i.price) < 700 
    ) AS ord
    LEFT JOIN orders mo ON ord.order_ID = mo.order_ID
    LEFT JOIN items  mi ON mo.item_ID = mi.id
    ORDER BY ord.order_id, mo.quantity, mi.price;

结果

+----------+---------+----------+--------+
| order_ID | item_ID | quantity | price  |
+----------+---------+----------+--------+
|      115 |      47 |        1 |  30.00 |
|      115 |      41 |        3 |  42.00 |
|      115 |      39 |        3 |  60.00 |
|      150 |      47 |        1 |  30.00 |
|      150 |      41 |        3 |  42.00 |
|      150 |      39 |        3 |  60.00 |
|      177 |      46 |        2 | 120.00 |
|      177 |      42 |        2 | 120.00 |
|      177 |      45 |        3 | 180.00 |
+----------+---------+----------+--------+
9 rows in set (0.06 sec)