如何为订单及其商品编写自定义MySQL选择查询

时间:2015-10-26 21:30:47

标签: mysql join count sum having

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

背景

两个表:ordersitems,每个表都包含唯一信息(它们使用ID相互连接;没有重复数据)。参见附录A和B(见下文)。

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

问题

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

  • 项目数(产品)
  • 件数(产品数量)
  • 成本(总订单成本:产品数量乘以产品成本)

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

  • 每个订单的商品数量
  • 商品ID
  • 购买数量(每种产品)

实施例

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

  • 三项(产品)
  • 七件(总量)
  • 不到600美元

如果所有数据(订单和项目)都包含在一个表中,则查询将如下所示:

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(*)

并返回这样的内容:

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

但由于价格存储在一个单独的表中,因此更复杂。我创建了这个查询(参见图表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`

让我接近,但让我想要定价信息。我已尝试使用JOINSWhat's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?),但几小时后仍无法正常使用。

问题

是否可以在一个MySQL查询中检索所有这些数据,和/或是否有比我目前使用的路径更好的方法(你会做什么)?

查询返回类似于此的结果是可以接受的:

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

只要查询要求生成的订单包含三个项目和七个部分,总计少于600美元(根据提供的示例)。

我也辞职了,这可能在一个查询中无法实现,并且知道如何使用PHP实现这一点;我想我可能会尽可能地在MySQL中做大部分工作,并在今天学习一些东西。 :)

你们中的一些人可能会建议更改表格结构,但我真的不会有重复数据的表格,如果可以提供帮助:如果产品价格发生变化,我会这样做而不必在两个表中更新。

感谢您的时间和任何解决方案;我非常感谢你们所能提供的任何帮助。

展品/视觉辅助设施

图表A:orders

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:items

(提供完整性,非关键信息) 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

1 个答案:

答案 0 :(得分:0)

我将从这里开始,我一步一步地完成它。

首先, LEFT JOIN 是您的朋友。所以你可以得到每个项目的价格

示例1:

使用此查询,您可以从表订单中获得前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:

现在,您的查询必须分为两部分。首先,我们将获得具有您的标准(物品,件数和价格)的所有oder 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 ,但它不适合小提琴。我有一个暂停。请在您的服务器上查看。

我也看到你的桌子上没有好的索引。所以Querys可以非常慢

  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)